home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / Xpm / pixmap / Graphics.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  72KB  |  2,656 lines

  1. /* * Last edited: Dec 19 10:46 1991 (mallet) */
  2. /*
  3.  * $Id: Graphics.c,v 1.8 1992/10/16 16:37:29 mallet Exp $
  4.  * 
  5.  * Copyright 1991 Lionel Mallet
  6.  * 
  7.  * Permission to use, copy, modify, distribute, and sell this software and its
  8.  * documentation for any purpose is hereby granted without fee, provided that
  9.  * the above copyright notice appears in all copies and that both that
  10.  * copyright notice and this permission notice appear in supporting
  11.  * documentation, and that the name of Lionel MALLET not be used in
  12.  * advertising or publicity pertaining to distribution of the software
  13.  * without specific, written prior permission.  Lionel MALLET makes no
  14.  * representations about the suitability of this software for any
  15.  * purpose.  It is provided "as is" without express or implied warranty.
  16.  *
  17.  * Lionel MALLET DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
  18.  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  19.  * FITNESS, IN NO EVENT SHALL Lionel MALLET BE LIABLE FOR ANY SPECIAL,
  20.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
  21.  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 
  22.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  23.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  24.  *
  25.  *  This software is opened and free. Furthermore, everybody is kindly
  26.  * invited to participate to improve it for the benefit of all.
  27.  * Improvements can be new features, bugs fixes and porting issues
  28.  * resolution.
  29.  *
  30.  * Author:  Lionel Mallet, SIMULOG
  31.  */
  32.  
  33. /*
  34.  * $XConsortium: Graphics.c,v 1.1 90/06/09 20:20:29 dmatic Exp $
  35.  *
  36.  * Copyright 1989 Massachusetts Institute of Technology
  37.  *
  38.  * Permission to use, copy, modify, distribute, and sell this software and its
  39.  * documentation for any purpose is hereby granted without fee, provided that
  40.  * the above copyright notice appear in all copies and that both that
  41.  * copyright notice and this permission notice appear in supporting
  42.  * documentation, and that the name of M.I.T. not be used in advertising or
  43.  * publicity pertaining to distribution of the software without specific,
  44.  * written prior permission.  M.I.T. makes no representations about the
  45.  * suitability of this software for any purpose.  It is provided "as is"
  46.  * without express or implied warranty.
  47.  *
  48.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  49.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  50.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  51.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  52.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  53.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  54.  *
  55.  * Author:  Davor Matic, MIT X Consortium
  56.  */
  57.  
  58.  
  59.  
  60. #include <X11/IntrinsicP.h>
  61. #include <X11/Xmu/Converters.h>
  62. #include <X11/StringDefs.h>
  63. #include <X11/Xatom.h>
  64. #include <X11/Xutil.h>
  65. #include <X11/Xos.h>
  66. #include "PixmapP.h"
  67.  
  68. #include <stdio.h>
  69. #include <math.h>
  70.  
  71. #define XtStrlen(s)                   ((s) ? strlen(s) : 0)
  72. #define abs(x)                        (((x) > 0) ? (x) : -(x))
  73. #define min(x, y)                     (((x) < (y)) ? (x) : (y))
  74. #define max(x, y)                     (((x) > (y)) ? (x) : (y))
  75.  
  76.  
  77. /**************************************************************************
  78.  *
  79.  * Utility functions
  80.  *
  81.  **************************************************************************/
  82.  
  83. typedef enum { Lazy, NotLazy} DrawingMode;
  84.  
  85. #define WithinMark(PW, xi, yi) \
  86.   ((xi <= max(PW->pixmap.mark.from_x, PW->pixmap.mark.to_x)) &&\
  87.    (xi >= min(PW->pixmap.mark.from_x, PW->pixmap.mark.to_x)) &&\
  88.    (yi <= max(PW->pixmap.mark.from_y, PW->pixmap.mark.to_y)) &&\
  89.    (yi >= min(PW->pixmap.mark.from_y, PW->pixmap.mark.to_y)))
  90.  
  91. #define HotInMark(PW) WithinMark(PW, PW->pixmap.hot.x, PW->pixmap.hot.y)
  92.  
  93. #define IsHotSpot(PW, xi, yi) \
  94.   ((xi== PW->pixmap.hot.x) && (yi == PW->pixmap.hot.y))
  95.  
  96. Pixel GetPxlFromImageAndMask(image, mask_image, x, y)
  97.      XImage *image, *mask_image;
  98.      Position x, y;
  99. {
  100.     Pixel pixel;
  101.  
  102.     pixel = XGetPixel(image, x, y);
  103.     if (XGetPixel(mask_image, x, y) == 0) return TRANSPARENT(dpy, screen);
  104.     else return pixel;
  105. }
  106.  
  107.     
  108. Pixel GetPxl(pw, x, y)
  109.      PixmapWidget pw;
  110.      Position x, y;
  111. {
  112.     Pixel pixel;
  113.     
  114.     pixel = XGetPixel(pw->pixmap.image, x, y);
  115.     if ((pixel == pw->pixmap.transparent_pixel) &&
  116.     (XGetPixel(pw->pixmap.mask_image, x, y) == 0))
  117.       return TRANSPARENT(dpy, screen);
  118.     else return pixel;
  119. }
  120.  
  121. void SetPxl(pw, x, y, color)
  122.      PixmapWidget pw;
  123.      Position x, y;
  124.      Pixel color;
  125. {
  126.     if (color == TRANSPARENT(dpy, screen))
  127.     {
  128.     XPutPixel(pw->pixmap.image, x, y, pw->pixmap.transparent_pixel);
  129.     XPutPixel(pw->pixmap.mask_image, x, y, 0);
  130.     }
  131.     else 
  132.     {
  133.     XPutPixel(pw->pixmap.image, x, y, color);
  134.     XPutPixel(pw->pixmap.mask_image, x, y, 1);
  135.     }
  136. }
  137.       
  138.  
  139. #define ClearPxl(pw, x, y, white)\
  140.   SetPxl(pw, x, y, white)
  141.  
  142.  
  143. #if NeedFunctionPrototypes
  144. Pixel PWGetPxl(Widget w, Position x, Position y)
  145. #else
  146. Pixel PWGetPxl(w, x, y)
  147.      Widget  w;
  148.      Position      x, y;
  149. #endif
  150. {
  151.   PixmapWidget PW = (PixmapWidget) w;
  152.   Pixel pixel;
  153.   
  154.   if (QueryInPixmap(PW, x, y))
  155.     return GetPxl(PW, x, y);
  156.   else
  157.     return NotSet;
  158. }
  159.  
  160.  
  161. XPoint *HotSpotShape(PW, x ,y)
  162.     PixmapWidget PW;
  163.     Position     x, y;
  164. {
  165.     static XPoint points[5];
  166.   
  167.     points[0].x = InWindowX(PW, x);
  168.     points[0].y = InWindowY(PW, y + 1.0/2);
  169.     points[1].x = InWindowX(PW, x + 1.0/2);
  170.     points[1].y = InWindowY(PW, y + 1);
  171.     points[2].x = InWindowX(PW, x + 1);
  172.     points[2].y = InWindowY(PW, y + 1.0/2);
  173.     points[3].x = InWindowX(PW, x + 1.0/2);
  174.     points[3].y = InWindowY(PW, y);
  175.     points[4].x = InWindowX(PW, x);
  176.     points[4].y = InWindowY(PW, y + 1.0/2);
  177.     
  178.     return points;
  179. }
  180.  
  181. #define DrawHotSpot(PW, x, y)\
  182.   XFillPolygon(XtDisplay(PW), XtWindow(PW), PW->pixmap.framing_gc,\
  183.            HotSpotShape(PW, x, y), 5, Convex, CoordModeOrigin)
  184.  
  185. #define HighlightHotSpot(PW, x, y)\
  186.   XFillPolygon(XtDisplay(PW), XtWindow(PW), PW->pixmap.highlighting_gc,\
  187.            HotSpotShape(PW, x, y), 5, Convex, CoordModeOrigin)
  188.  
  189.  
  190. void HighlightSquare(PW, x, y)
  191.      PixmapWidget PW;
  192.      Position x, y;
  193. {
  194.   XFillRectangle(dpy, XtWindow(PW),
  195.          PW->pixmap.highlighting_gc,
  196.          InWindowX(PW, x), InWindowY(PW, y),
  197.          PW->pixmap.squareW, PW->pixmap.squareH);
  198. }
  199.  
  200. void RedrawAxesInSquare();
  201.  
  202.  
  203. void ClearSquare(PW, x, y)
  204.      PixmapWidget PW;
  205.      Position x, y;
  206. {
  207.   XSetForeground(dpy, PW->pixmap.drawing_gc, PW->pixmap.clear_pixel);
  208.   XFillRectangle(dpy, XtWindow(PW),
  209.          PW->pixmap.drawing_gc,
  210.          InWindowX(PW, x), InWindowY(PW, y),
  211.          PW->pixmap.squareW, PW->pixmap.squareH);
  212.  
  213. }
  214.  
  215.  
  216. void DrawSquare(PW, x, y, color)
  217.      PixmapWidget PW;
  218.      Position x, y;
  219.      Pixel color;
  220. {
  221.   if (color == PW->pixmap.clear_pixel) ClearSquare(PW, x, y);
  222.   else if (color == TRANSPARENT(dpy, screen))
  223.     {
  224.       XFillRectangle(dpy, XtWindow(PW),
  225.              PW->pixmap.transparent_gc,
  226.              InWindowX(PW, x), InWindowY(PW, y),
  227.              PW->pixmap.squareW, PW->pixmap.squareH);
  228.     }
  229.   else
  230.     {
  231.       XSetForeground(dpy, PW->pixmap.drawing_gc, color);
  232.       XFillRectangle(dpy, XtWindow(PW),
  233.              PW->pixmap.drawing_gc,
  234.              InWindowX(PW, x), InWindowY(PW, y),
  235.              PW->pixmap.squareW, PW->pixmap.squareH);
  236.       XSetForeground(dpy,PW->pixmap.drawing_gc,
  237.              PW->pixmap.foreground_pixel);
  238.     }
  239. }
  240.  
  241. #define DrawPoint(PW, x, y, color, mode)\
  242.   if ((mode == NotLazy) || (GetPxl(PW, x, y) != color)) {\
  243.     DrawSquare(PW, x, y, color); \
  244.     SetPxl(PW, x, y, color); \
  245.     /* now put back the status of the pixel */ \
  246.     PWRedrawGrid((Widget )PW, x, y, x, y); \
  247.     RedrawAxesInSquare(PW, x, y); \
  248.     if (WithinMark(PW, x, y)) HighlightSquare(PW, x, y); \
  249.     if (IsHotSpot(PW, x, y)) PWRedrawHotSpot((Widget)PW);\
  250.     if (PW->pixmap.drawPointCallback) \
  251.         PW->pixmap.drawPointCallback( (Widget) PW, x, y, Highlight );\
  252.   }
  253.  
  254. #define ClearPoint(PW, x, y, mode) \
  255.   if ((mode == NotLazy) || \
  256.       (GetPxl(PW, x, y) != PW->pixmap.clear_pixel)) {\
  257.     ClearSquare(PW, x, y);  \
  258.     ClearPxl(PW, x, y, PW->pixmap.clear_pixel); \
  259.     /* now put back the status of the pixel */ \
  260.     PWRedrawGrid((Widget)PW, x, y, x, y); \
  261.     RedrawAxesInSquare(PW, x, y); \
  262.     if (WithinMark(PW, x, y)) HighlightSquare(PW, x, y); \
  263.     if (IsHotSpot(PW, x, y)) PWRedrawHotSpot((Widget)PW);\
  264.     if (PW->pixmap.drawPointCallback) \
  265.         PW->pixmap.drawPointCallback( (Widget) PW, x, y, Highlight );\
  266.   }
  267.  
  268.  
  269. #define QueryFlood(PW, x, y, value)\
  270.   (QueryInPixmap(PW, x, y)\
  271.      && (GetPxl(PW, x, y) == value))
  272.  
  273. #define Flood(PW, x, y, value)\
  274.   DrawPoint(PW, x, y, value, NotLazy)
  275.  
  276. void FloodLoop(PW, x, y, value, toflood)
  277.      PixmapWidget PW;
  278.      Position     x, y;
  279.      Pixel          value, toflood;
  280. {
  281.   Position save_x, save_y, x_left, x_right;
  282.  
  283.   if (value == toflood) return; /* nothing to flood in this case */
  284.   
  285.   if (QueryFlood(PW, x, y, toflood)) 
  286.     Flood(PW, x, y, value);
  287.       
  288.   save_x = x;
  289.   save_y = y;
  290.   
  291.   x++;
  292.   while (QueryFlood(PW, x, y, toflood)) {
  293.     Flood(PW, x, y, value);
  294.     x++;
  295.   }
  296.   x_right = --x;
  297.   
  298.   x = save_x;
  299.   x--;
  300.   while (QueryFlood(PW, x, y, toflood)) {
  301.     Flood(PW, x, y, value);
  302.     x--;
  303.   }
  304.   x_left = ++x;
  305.   
  306.   
  307.   x = x_left;
  308.   y = save_y;
  309.   y++;
  310.   
  311.   while (x <= x_right) {
  312.     Boolean flag = False;
  313.     Position x_enter;
  314.     
  315.     while (QueryFlood(PW, x, y, toflood) && (x <= x_right)) {
  316.       flag = True;
  317.       x++;
  318.     }
  319.     
  320.     if (flag) {
  321.       if ((x == x_right) && QueryFlood(PW, x, y, toflood))
  322.     FloodLoop(PW, x, y, value, toflood);
  323.       else
  324.     FloodLoop(PW, x - 1, y, value, toflood);
  325.     }
  326.     
  327.     x_enter = x;
  328.     
  329.     while (!QueryFlood(PW, x, y, toflood) && (x < x_right))
  330.       x++;
  331.     
  332.     if (x == x_enter) x++;
  333.   }
  334.   
  335.   x = x_left;
  336.   y = save_y;
  337.   y--;
  338.   
  339.   while (x <= x_right) {
  340.     Boolean flag = False;
  341.     Position x_enter;
  342.     
  343.     while (QueryFlood(PW, x, y, toflood) && (x <= x_right)) {
  344.       flag = True;
  345.       x++;
  346.     }
  347.     
  348.     if (flag) {
  349.       if ((x == x_right) && QueryFlood(PW, x, y, toflood))
  350.     FloodLoop(PW, x, y, value, toflood);
  351.       else
  352.     FloodLoop(PW, x - 1, y, value, toflood);
  353.     }
  354.     
  355.     x_enter = x;
  356.     
  357.     while (!QueryFlood(PW, x, y, toflood) && (x < x_right))
  358.       x++;
  359.     
  360.     if (x == x_enter) x++;
  361.   }
  362. }
  363.  
  364. void CopyImageData(source, destination, from_x, from_y, to_x, to_y, at_x, at_y)
  365.      XImage *source, *destination;
  366.      Position  from_x, from_y, to_x, to_y, at_x, at_y;
  367. {
  368.   register Position x, y, delta_x, delta_y;
  369.   
  370.   delta_x = to_x - from_x + 1;
  371.   delta_y = to_y - from_y + 1;
  372.   
  373.   for (x = 0; x < delta_x; x++)
  374.     for (y = 0; y < delta_y; y++)
  375.       XPutPixel(destination, at_x + x, at_y + y, 
  376.          XGetPixel(source, from_x + x, from_y + y));
  377. }
  378.  
  379.  
  380. void TransferImageData(source, destination)
  381.      XImage *source, *destination;
  382. {
  383.   register Position x, y;
  384.   register Pixel color;
  385.   
  386.   for (x = 0; x < min(source->width, destination->width); x++)
  387.     for (y = 0; y < min(source->height, destination->height); y++)
  388.       if ((color = XGetPixel(source, x, y)) != XGetPixel(destination, x, y))
  389.     XPutPixel(destination, x, y, color);
  390. }
  391.  
  392. void DrawImageData(PW, image, mask_image, at_x, at_y, value, mode)
  393.      PixmapWidget PW;
  394.      XImage *image, *mask_image;
  395.      Position at_x, at_y;
  396.      int value;
  397.      DrawingMode mode;
  398. {
  399.   Position x, y;
  400.   Pixel      A, B;
  401.   register Pixel Cl, Fg, val;
  402.   
  403.   Cl = PW->pixmap.clear_pixel;
  404.   Fg = PW->pixmap.foreground_pixel;
  405.   
  406.   for (x = 0; x < image->width; x++) 
  407.     for (y = 0; y < image->height; y++) {
  408.       if (!QueryInPixmap(PW, at_x + x, at_y + y)) break;
  409.       A = GetPxlFromImageAndMask(image, mask_image, x, y);
  410.       B = GetPxl(PW, at_x + x, at_y + y);
  411.       switch (value)
  412.     {
  413.     case Clear:
  414.       if ((mode == NotLazy) || (B != Cl)) val = Cl;
  415.       else val = NotSet;
  416.       break;
  417.     case Set:
  418.       if ((mode == NotLazy) || (B != A)) val = A;
  419.       else val = NotSet;
  420.       break;
  421.     case Invert:
  422.       if (((mode == NotLazy) && (A != Cl)) || ((A != Cl) && (B != Cl)))
  423.         val = Cl;
  424.       else if (((mode == NotLazy) && (A == Cl)) || 
  425.            ((A == Cl) && (B != Fg))) val = Fg;
  426.       else val = NotSet;
  427.       break;
  428.     case Highlight:
  429.       if (A != B) PWDrawPoint((Widget)PW, at_x + x, at_y + y, A);
  430.       break;
  431.     }
  432.       if ((val != NotSet) && (val != Highlight))
  433.     {
  434.       DrawPoint(PW, at_x + x, at_y + y, val, mode);
  435.     }
  436.       else 
  437.     if (value == Highlight) HighlightSquare(PW, x, y);
  438.     
  439.     }
  440. }
  441.  
  442. #define PRECISION 0.00001
  443. #define OR(p1, p2) (p1 ? p1 : (p2 ? p2 : NULL))
  444.  
  445. /* this function checks the intersection of two lines
  446.  * returns intersection if it exists, first point if two lines are equal,
  447.  * null otherwise. Space in which result in returned should be free by the
  448.  * caller
  449.  */
  450. XPoint *intersect(P1, Q1, P2, Q2)
  451.      XPoint P1, Q1, P2, Q2;
  452.      
  453. {
  454.   XPoint *result;
  455.   int vert1 = 0, vert2 = 0, horiz1 = 0, horiz2 = 0;
  456.   double alpha1, beta1, alpha2, beta2;
  457.   double x, y;
  458.  
  459.   if (P1.x != Q1.x) /* not vertical */
  460.     {
  461.       alpha1 = (Q1.y*1. - P1.y*1.) / (Q1.x*1. - P1.x*1.);
  462.       beta1 = P1.y*1. - alpha1 * P1.x*1.;
  463.       if (Q1.y == P1.y) horiz1 = 1;
  464.     }
  465.   else /* vertical */
  466.     {
  467.       vert1 = 1;
  468.       /* check line1 not point */
  469.       if (P1.y == Q1.y) return(NULL);
  470.       alpha1 = 0.;
  471.       beta1 = P1.x;
  472.     }
  473.  
  474.   if (P2.x != Q2.x) /* not vertical */
  475.     {
  476.       if (P2.y == Q2.y) horiz2 = 1;
  477.       if (!vert1)
  478.     {
  479.       alpha2 = (Q2.y*1. - P2.y*1.) / (Q2.x*1. - P2.x*1.);
  480.       beta2 = P2.y*1. - alpha2 * P2.x*1.;
  481.     }
  482.       else if (!horiz2) /* and vert1 implicitly */
  483.     {
  484.       alpha2 = (Q2.x*1. - P2.x*1.) / (Q2.y*1. - P2.y*1.);
  485.       beta2 = P2.x*1. - alpha2 * P2.y*1.;
  486.     }
  487.       else /* vert1 and horiz2 */
  488.     {
  489.       alpha2 = 0.;
  490.       beta2 = P2.y;
  491.     }
  492.     }
  493.   else /* vertical */
  494.     {
  495.       vert2 = 1;
  496.       /* check line2 not point */
  497.       if (P2.y == Q2.y) return(NULL);
  498.       alpha2 = 0.;
  499.       beta2 = P2.x;
  500.       if ((!vert1) && (!horiz1))
  501.     {
  502.       alpha1 = (Q1.x*1. - P1.x*1.) / (Q1.y*1. - P1.y*1.);
  503.       beta1 = P1.x*1. - alpha1 * P1.y*1.;
  504.     }      
  505.     }
  506.   
  507. #ifdef DEBUG
  508.   printf("D1 vert %d horiz %d, D2 vert %d horiz %d\n", vert1, horiz1, 
  509.      vert2, horiz2);
  510.   printf("alpha1 %lf beta1 %lf, alpha2 %lf beta2 %lf\n", alpha1, beta1,
  511.      alpha2, beta2);
  512. #endif DEBUG
  513.  
  514.   if ((vert1 && vert2) || (horiz1 && horiz2))
  515.     {
  516.       if (!fabs(beta1 - beta2) > PRECISION) return(NULL);
  517.       x = P1.x;
  518.       y = P1.y;
  519.     }
  520.   else if ((vert1 && horiz2) || (vert2 && horiz1))
  521.     {
  522.       if (vert1)
  523.       x = P1.x , y = P2.y;
  524.       else 
  525.       x = P2.x , y = P1.y;
  526.     }
  527.   else if ((vert1 && !vert2 && !horiz2) || (vert2 && !vert1 && !horiz1))
  528.     {
  529.       if (vert1)
  530.       x = P1.x , y = (x - beta2) / alpha2;
  531.       else x = P2.x , y = (x - beta1) / alpha1;
  532.     }
  533.   else if ((horiz1 && !vert2 && !horiz2) || (horiz2 && !vert1 && !horiz1))
  534.     {
  535.       if (horiz1)
  536.     y = P1.y , x = (y - beta2) / alpha2;
  537.       else y = P2.y , x = (y - beta1) / alpha1;
  538.     }
  539.   else if (!vert1 && !horiz1 && !vert2 && !horiz2)
  540.     {
  541.       if (fabs(alpha1 - alpha2) > PRECISION) /* alpha1 != alpha2 */
  542.     {
  543.       x = (beta2 - beta1) / (alpha1 - alpha2);
  544.       y = alpha1 * x + beta1;
  545.     }
  546.       else if (fabs(beta1 - beta2) > PRECISION) /* alpha1 = alpha2
  547.                            && beta1 != beta2 */
  548.     return(NULL);
  549.       else /* alpha1 = alpha2 && beta1 = beta2 */
  550.     x = P1.x , y = P1.y;
  551.     }
  552.  
  553.   /* now check if solution in between P1, Q1 and P2, Q2, else return NULL */
  554.   if (((Position)rint(x) < min(P1.x, Q1.x)) || 
  555.       ((Position)rint(x) > max(P1.x, Q1.x)) ||
  556.       ((Position)rint(y) < min(P1.y, Q1.y)) ||
  557.       ((Position)rint(y) > max(P1.y, Q1.y)) ||
  558.       ((Position)rint(x) < min(P2.x, Q2.x)) || 
  559.       ((Position)rint(x) > max(P2.x, Q2.x)) ||
  560.       ((Position)rint(y) < min(P2.y, Q2.y)) ||
  561.       ((Position)rint(y) > max(P2.y, Q2.y)))
  562.     return(NULL);
  563.   else
  564.     {
  565.       result = (XPoint *) XtMalloc(sizeof(XPoint));
  566.       result->x = (Position) rint(x);
  567.       result->y = (Position) rint(y);
  568.       return(result);
  569.     }
  570. }
  571.  
  572.  
  573. /* the algorithm is : find A1, A2, B1, B2 intersections of the axe to draw
  574.  * and the borders of the square (t, l, b, r) and then draw line between
  575.  * (A1 or A2) and (B1 or B2) 
  576.  */
  577. void RedrawAxesInSquare(PW, x, y)
  578.      PixmapWidget PW;
  579.      Position x, y;
  580. {
  581.   int w = PW->pixmap.width, h =PW->pixmap.height;
  582.   XPoint P1, Q1, P2, Q2, *A1, *A2, *B1, *B2, *from, *to;
  583.  
  584.   if (PWQueryAxes((Widget)PW))
  585.     {
  586.       /* first diagonal */
  587.       P2.x = InWindowX(PW, 0); P2.y = InWindowY(PW, 0);
  588.       Q2.x = InWindowX(PW, w); Q2.y = InWindowY(PW, h);
  589.       
  590.       /* A1: top intersect diagonal */
  591.       P1.x = InWindowX(PW, x); P1.y = InWindowY(PW, y);
  592.       Q1.x = InWindowX(PW, x+1); Q1.y = P1.y;
  593.       A1 = intersect(P1, Q1, P2, Q2);
  594.       
  595.       /* A2: left intersect diagonal */
  596.       P1.x = InWindowX(PW, x); P1.y = InWindowY(PW, y);
  597.       Q1.x = P1.x; Q1.y = InWindowY(PW, y+1);
  598.       A2 = intersect(P1, Q1, P2, Q2);
  599.       
  600.       /* B1: bottom intersect diagonal */
  601.       P1.x = InWindowX(PW, x); P1.y = InWindowY(PW, y+1);
  602.       Q1.x = InWindowX(PW, x+1); Q1.y = P1.y;
  603.       B1 = intersect(P1, Q1, P2, Q2);
  604.       
  605.       /* B2: right intersect diagonal */
  606.       P1.x = InWindowX(PW, x+1); P1.y = InWindowY(PW, y);
  607.       Q1.x = P1.x; Q1.y = InWindowY(PW, y+1);
  608.       B2 = intersect(P1, Q1, P2, Q2);
  609.       
  610.       /* line to draw from=OR(a1, a2) to=OR(b1, b2) */
  611.       from = OR(A1, A2); to = OR(B1, B2);
  612.       if (from && to) XDrawLine(dpy, XtWindow(PW), PW->pixmap.framing_gc,
  613.                 from->x, from->y, to->x, to->y);
  614.       if (A1) free(A1); if (A2) free(A2);
  615.       if (B1) free(B1); if (B2) free(B2);
  616.       
  617.       /* second diagonal */
  618.       P2.x = InWindowX(PW, 0); P2.y = InWindowY(PW, h);
  619.       Q2.x = InWindowX(PW, w); Q2.y = InWindowY(PW, 0);
  620.       
  621.       /* A1: top intersect diagonal */
  622.       P1.x = InWindowX(PW, x); P1.y = InWindowY(PW, y);
  623.       Q1.x = InWindowX(PW, x+1); Q1.y = P1.y;
  624.       A1 = intersect(P1, Q1, P2, Q2);
  625.       
  626.       /* A2: right intersect diagonal */
  627.       P1.x = InWindowX(PW, x+1); P1.y = InWindowY(PW, y);
  628.       Q1.x = P1.x; Q1.y = InWindowY(PW, y+1);
  629.       A2 = intersect(P1, Q1, P2, Q2);
  630.       
  631.       /* B1: bottom intersect diagonal */
  632.       P1.x = InWindowX(PW, x); P1.y = InWindowY(PW, y+1);
  633.       Q1.x = InWindowX(PW, x+1); Q1.y = P1.y;
  634.       B1 = intersect(P1, Q1, P2, Q2);
  635.       
  636.       /* B2: left intersect diagonal */
  637.       P1.x = InWindowX(PW, x); P1.y = InWindowY(PW, y);
  638.       Q1.x = P1.x; Q1.y = InWindowY(PW, y+1);
  639.       B2 = intersect(P1, Q1, P2, Q2);
  640.       
  641.       /* line to draw from=OR(a1, a2) to=OR(b1, b2) */
  642.       from = OR(A1, A2); to = OR(B1, B2);
  643.       if (from && to) XDrawLine(dpy, XtWindow(PW), PW->pixmap.framing_gc,
  644.                 from->x, from->y, to->x, to->y);
  645.       if (A1) free(A1); if (A2) free(A2);
  646.       if (B1) free(B1); if (B2) free(B2);
  647.  
  648.       /* horizontal */
  649.       if (((h % 2) != 0) || (!PWQueryGrid((Widget)PW))) /* height is even 
  650.                                                            or grid is off */
  651.     {
  652.       Position y0;
  653.       
  654.       y0 = InWindowY(PW, 0)
  655.         + rint((InWindowY(PW, h) - InWindowY(PW, 0)) / 2.);
  656.       if ((y0 > InWindowY(PW, y)) && (y0 < InWindowY(PW, y+1)))
  657.         XDrawLine(dpy, XtWindow(PW), PW->pixmap.framing_gc,
  658.               InWindowX(PW, x), y0, InWindowX(PW, x+1), y0);
  659.     }
  660.       
  661.       /* vertical */
  662.       if (((w % 2) != 0) || (!PWQueryGrid((Widget)PW))) /* width is even 
  663.                                                            or grid is off */
  664.     {
  665.       Position x0;
  666.       
  667.       x0 = InWindowX(PW, 0)
  668.         + rint((InWindowX(PW, w) - InWindowX(PW, 0)) / 2.);
  669.       if ((x0 > InWindowX(PW, x)) && (x0 < InWindowX(PW, x+1)))
  670.         XDrawLine(dpy, XtWindow(PW), PW->pixmap.framing_gc,
  671.               x0, InWindowY(PW, y), x0, InWindowY(PW, y+1));
  672.     }
  673.     }
  674. }
  675.  
  676. typedef struct {
  677.   Position *x, *y;
  678.   Dimension *width, *height;
  679. } Table;
  680.  
  681. XImage *ScalePixmapImage(PW, src, scale_x, scale_y)
  682.      PixmapWidget PW;
  683.      XImage *src;
  684.      double scale_x, scale_y;
  685. {
  686.   XImage *dst;
  687.   Table table;    
  688.   Position x, y, w, h;
  689.   Dimension width, height;
  690.   Pixel pixel;
  691.   
  692.   width = max(rint(scale_x * src->width), 1);
  693.   height = max(rint(scale_y * src->height), 1);
  694.   
  695.   dst = CreatePixmapImage(PW, width, height);
  696.   
  697.   /*
  698.    * It would be nice to check if width or height < 1.0 and
  699.    * average the skipped pixels. But, it is slow as it is now.
  700.    */
  701.   if (scale_x == 1.0 && scale_y == 1.0)
  702.     CopyImageData(src, dst, 0, 0, width-1 , height-1, 0, 0);
  703.   else {
  704.     table.x = (Position *) XtMalloc(sizeof(Position) * src->width);
  705.     table.y = (Position *) XtMalloc(sizeof(Position) * src->height);
  706.     table.width = (Dimension *) XtMalloc(sizeof(Dimension) * src->width);
  707.     table.height = (Dimension *) XtMalloc(sizeof(Dimension) * src->height);
  708.     
  709.     for (x = 0; x < src->width; x++) {
  710.       table.x[x] = rint(scale_x * x);
  711.       table.width[x] = rint(scale_x * (x + 1)) - rint(scale_x * x);
  712.     }
  713.     for (y = 0; y < src->height; y++) {
  714.       table.y[y] = rint(scale_y * y);
  715.       table.height[y] = rint(scale_y * (y + 1)) - rint(scale_y * y);
  716.     }
  717.     
  718.     for (x = 0; x < src->width; x++)
  719.       for (y = 0; y < src->height; y++) {
  720.     pixel = XGetPixel(src, x, y);
  721.     for (w = 0; w < table.width[x]; w++)
  722.       for (h = 0; h < table.height[y]; h++)
  723.         if (pixel != PW->pixmap.clear_pixel) XPutPixel(dst, 
  724.                                table.x[x] + w, 
  725.                                table.y[y] + h,
  726.                                pixel);
  727.       }
  728.     
  729.     XtFree((char *)table.x);
  730.     XtFree((char *)table.y);
  731.     XtFree((char *)table.width);
  732.     XtFree((char *)table.height);
  733.   }
  734.   
  735.   return (dst);
  736. }
  737.  
  738. XImage *ScaleMaskImage(PW, src, scale_x, scale_y)
  739.      PixmapWidget PW;
  740.      XImage *src;
  741.      double scale_x, scale_y;
  742. {
  743.   XImage *dst;
  744.   Table table;    
  745.   Position x, y, w, h;
  746.   Dimension width, height;
  747.   Pixel pixel;
  748.   
  749.   width = max(rint(scale_x * src->width), 1);
  750.   height = max(rint(scale_y * src->height), 1);
  751.   
  752.   dst = CreateMaskImage(PW, width, height);
  753.   
  754.   /*
  755.    * It would be nice to check if width or height < 1.0 and
  756.    * average the skipped pixels. But, it is slow as it is now.
  757.    */
  758.   if (scale_x == 1.0 && scale_y == 1.0)
  759.     CopyImageData(src, dst, 0, 0, width-1 , height-1, 0, 0);
  760.   else {
  761.     table.x = (Position *) XtMalloc(sizeof(Position) * src->width);
  762.     table.y = (Position *) XtMalloc(sizeof(Position) * src->height);
  763.     table.width = (Dimension *) XtMalloc(sizeof(Dimension) * src->width);
  764.     table.height = (Dimension *) XtMalloc(sizeof(Dimension) * src->height);
  765.     
  766.     for (x = 0; x < src->width; x++) {
  767.       table.x[x] = rint(scale_x * x);
  768.       table.width[x] = rint(scale_x * (x + 1)) - rint(scale_x * x);
  769.     }
  770.     for (y = 0; y < src->height; y++) {
  771.       table.y[y] = rint(scale_y * y);
  772.       table.height[y] = rint(scale_y * (y + 1)) - rint(scale_y * y);
  773.     }
  774.     
  775.     for (x = 0; x < src->width; x++)
  776.       for (y = 0; y < src->height; y++) {
  777.     pixel = XGetPixel(src, x, y);
  778.     for (w = 0; w < table.width[x]; w++)
  779.       for (h = 0; h < table.height[y]; h++)
  780.         if (pixel == 0) XPutPixel(dst, table.x[x] + w, table.y[y] + h,
  781.                       pixel);
  782.       }
  783.     
  784.     XtFree((char *)table.x);
  785.     XtFree((char *)table.y);
  786.     XtFree((char *)table.width);
  787.     XtFree((char *)table.height);
  788.   }
  789.   
  790.   return (dst);
  791. }
  792.  
  793.  
  794. /*************************************************************************
  795.  *
  796.  * Interface functions
  797.  *
  798.  *************************************************************************/
  799. /* high level procedures */
  800.  
  801. #if NeedFunctionPrototypes
  802. GC PWHighlightingGC(Widget w)
  803. #else
  804. GC PWHighlightingGC(w)
  805.     Widget w;
  806. #endif
  807. {
  808.     PixmapWidget PW = (PixmapWidget) w;
  809.     return PW->pixmap.highlighting_gc;
  810. }
  811.  
  812. #if NeedFunctionPrototypes
  813. GC PWFramingGC(Widget w)
  814. #else
  815. GC PWFramingGC(w)
  816.     Widget w;
  817. #endif
  818. {
  819.     PixmapWidget PW = (PixmapWidget) w;
  820.     return PW->pixmap.framing_gc;
  821. }
  822.  
  823. #if NeedFunctionPrototypes
  824. GC PWDrawingGC(Widget w)
  825. #else
  826. GC PWDrawingGC(w)
  827.     Widget w;
  828. #endif
  829. {
  830.     PixmapWidget PW = (PixmapWidget) w;
  831.     return PW->pixmap.drawing_gc;
  832. }
  833.  
  834. #if NeedFunctionPrototypes
  835. Position PWInWindowX(Widget w, float x)
  836. #else
  837. Position PWInWindowX(w,x)
  838.     Widget   w;
  839.     float    x;
  840. #endif
  841. {
  842.     return InWindowX( ((PixmapWidget) w), x );
  843. }
  844.  
  845. #if NeedFunctionPrototypes
  846. Position PWInWindowY(Widget w, float y)
  847. #else
  848. Position PWInWindowY(w,y)
  849.     Widget   w;
  850.     float    y;
  851. #endif
  852. {
  853.     return InWindowY( ((PixmapWidget) w), y );
  854. }
  855.  
  856.  
  857. #if NeedFunctionPrototypes
  858. void PWRedrawHotSpot(Widget w)
  859. #else
  860. void PWRedrawHotSpot(w)
  861.     Widget w;
  862. #endif
  863. {
  864.     PixmapWidget PW = (PixmapWidget) w;
  865.  
  866.     if (QuerySet(PW->pixmap.hot.x, PW->pixmap.hot.y))
  867.     DrawHotSpot(PW, PW->pixmap.hot.x, PW->pixmap.hot.y);
  868. }
  869.  
  870. #if NeedFunctionPrototypes
  871. void PWClearHotSpot(Widget w)
  872. #else
  873. void PWClearHotSpot(w)
  874.     Widget w;
  875. #endif
  876. {
  877.     PixmapWidget PW = (PixmapWidget) w;
  878.     
  879.     DrawHotSpot(PW, PW->pixmap.hot.x, PW->pixmap.hot.y);
  880.     PW->pixmap.hot.x = PW->pixmap.hot.y = NotSet;
  881. }
  882.  
  883. #if NeedFunctionPrototypes
  884. void PWDrawHotSpot(Widget w, Position x, Position y, int value)
  885. #else
  886. void PWDrawHotSpot(w, x, y, value)
  887.     Widget w;
  888.     Position x, y;
  889.     int value;
  890. #endif
  891. {
  892.     PixmapWidget PW = (PixmapWidget) w;
  893.     
  894.     if (QueryInPixmap(PW, x, y)) {
  895.     if (QuerySet(PW->pixmap.hot.x, PW->pixmap.hot.y) &&
  896.         ((PW->pixmap.hot.x == x) && (PW->pixmap.hot.y == y))) {
  897.         if ((value == Clear) || (value == Invert)) {
  898.         PWClearHotSpot(w);
  899.         }
  900.     }
  901.     else
  902.         if ((value == Set) || (value == Invert)) {
  903.         PWClearHotSpot(w);
  904.         DrawHotSpot(PW, x, y);
  905.         PW->pixmap.hot.x = x;
  906.         PW->pixmap.hot.y = y;
  907.         }
  908.     
  909.     if (value == Highlight)
  910.         HighlightHotSpot(PW, x, y); 
  911.     }
  912. }
  913.  
  914. #if NeedFunctionPrototypes
  915. void PWSetHotSpot(Widget w, Position x, Position y)
  916. #else
  917. void PWSetHotSpot(w, x, y)
  918.     Widget w;
  919.     Position x, y;
  920. #endif
  921. {
  922.     if (QuerySet(x, y))
  923.     PWDrawHotSpot(w, x, y, Set);
  924.     else
  925.     PWClearHotSpot(w);
  926. }
  927.  
  928. #if NeedFunctionPrototypes
  929. void PWDrawPoint(Widget w, Position x, Position y, int value)
  930. #else
  931. void PWDrawPoint(w, x, y, value)
  932.      Widget  w;
  933.      Position      x, y;
  934.      int           value;
  935. #endif
  936. {
  937.   PixmapWidget PW = (PixmapWidget) w;
  938.   
  939.   if (QueryInPixmap(PW, x, y)) 
  940.     {
  941.       if (value == Highlight)
  942.     HighlightSquare(PW, x, y);
  943.       else if ((value == Clear) || 
  944.            ((value == Invert) && 
  945.         (GetPxl(PW, x, y) != PW->pixmap.clear_pixel)))
  946.     {
  947.       ClearPoint(PW, x, y, Lazy);
  948.     }
  949.       else /* value == Set || (value == Invert && Pxl == clear_pixel) */
  950.     {
  951.       DrawPoint(PW, x, y, PW->pixmap.foreground_pixel, Lazy);
  952.     }
  953.     }
  954. }
  955.  
  956. #if NeedFunctionPrototypes
  957. void PWRedrawSquares(Widget w, Position from_x, Position from_y, 
  958.              Position to_x, Position to_y)
  959. #else
  960. void PWRedrawSquares(w, from_x, from_y, to_x, to_y)
  961.      Widget  w;
  962.      Position from_x, from_y, to_x, to_y;
  963. #endif
  964. {
  965.   PixmapWidget PW = (PixmapWidget) w;
  966.   register int x, y;
  967.   
  968.   QuerySwap(from_x, to_x);
  969.   QuerySwap(from_y, to_y);
  970.   from_x = max(0, from_x);
  971.   from_y = max(0, from_y);
  972.   to_x = min(PW->pixmap.image->width - 1, to_x);
  973.   to_y = min(PW->pixmap.image->height - 1, to_y);
  974.   
  975.   for (x = from_x; x <= to_x; x++)
  976.     for (y = from_y; y <= to_y; y++)
  977.       DrawSquare(PW, x, y, GetPxl(PW, x, y));
  978. }
  979.  
  980. #if NeedFunctionPrototypes
  981. void PWRedrawPoints(Widget w, Position from_x, Position from_y, 
  982.              Position to_x, Position to_y)
  983. #else
  984. void PWRedrawPoints(w, from_x, from_y, to_x, to_y)
  985.      Widget  w;
  986.      Position from_x, from_y, to_x, to_y;
  987. #endif
  988. {
  989.   PixmapWidget PW = (PixmapWidget) w;
  990.   register int x, y;
  991.   
  992.   QuerySwap(from_x, to_x);
  993.   QuerySwap(from_y, to_y);
  994.   from_x = max(0, from_x);
  995.   from_y = max(0, from_y);
  996.   to_x = min(PW->pixmap.image->width - 1, to_x);
  997.   to_y = min(PW->pixmap.image->height - 1, to_y);
  998.   
  999.   for (x = from_x; x <= to_x; x++)
  1000.     for (y = from_y; y <= to_y; y++)
  1001.       DrawPoint(PW, x, y, GetPxl(PW, x, y), NotLazy);
  1002. }
  1003.  
  1004. #if NeedFunctionPrototypes
  1005. void PWDrawGrid(Widget w, Position from_x, Position from_y, 
  1006.         Position to_x, Position to_y)
  1007. #else
  1008. void PWDrawGrid(w, from_x, from_y, to_x, to_y)
  1009.      Widget w;
  1010.      Position from_x, from_y, to_x, to_y;
  1011. #endif
  1012. {
  1013.   PixmapWidget PW = (PixmapWidget) w;
  1014.   int i;
  1015.   
  1016.   QuerySwap(from_x, to_x);
  1017.   QuerySwap(from_y, to_y);
  1018.   from_x = max(0, from_x);
  1019.   from_y = max(0, from_y);
  1020.   to_x = min(PW->pixmap.image->width - 1, to_x);
  1021.   to_y = min(PW->pixmap.image->height - 1, to_y);
  1022.   
  1023.   for(i = from_x + (from_x == 0); i <= to_x; i++)
  1024.     XDrawLine(dpy, XtWindow(PW), 
  1025.           PW->pixmap.framing_gc,
  1026.           InWindowX(PW, i), InWindowY(PW, from_y),
  1027.           InWindowX(PW, i), InWindowY(PW, to_y + 1));
  1028.   
  1029.   for(i = from_y + (from_y == 0); i <= to_y; i++)
  1030.     XDrawLine(dpy, XtWindow(PW), 
  1031.           PW->pixmap.framing_gc,
  1032.           InWindowX(PW, from_x), InWindowY(PW, i),
  1033.           InWindowX(PW, to_x + 1), InWindowY(PW, i));
  1034. }
  1035.  
  1036.  
  1037. #if NeedFunctionPrototypes
  1038. void PWRedrawGrid(Widget w, Position from_x, Position from_y, 
  1039.           Position to_x, Position to_y)
  1040. #else
  1041. void PWRedrawGrid(w, from_x, from_y, to_x, to_y)
  1042.      Widget w;
  1043.      Position from_x, from_y, to_x, to_y;
  1044. #endif
  1045. {
  1046.   PixmapWidget PW = (PixmapWidget) w;
  1047.   
  1048.   if (PW->pixmap.grid)
  1049.     PWDrawGrid(w, from_x, from_y, to_x, to_y);
  1050. }
  1051.  
  1052. #if NeedFunctionPrototypes
  1053. void PWDrawLine(Widget w, Position from_x, Position from_y, 
  1054.         Position to_x, Position to_y, int value)
  1055. #else
  1056. void PWDrawLine(w, from_x, from_y, to_x, to_y, value)
  1057.      Widget  w;
  1058.      Position from_x, from_y, to_x, to_y;
  1059.      int value;
  1060. #endif
  1061. {
  1062.   Position i;
  1063.   register double x, y;
  1064.   double dx, dy, delta;
  1065.   
  1066.   dx = to_x - from_x;
  1067.   dy = to_y - from_y;
  1068.   x = from_x + 0.5;
  1069.   y = from_y + 0.5;
  1070.   delta = max(abs(dx), abs(dy));
  1071.   if (delta > 0) {
  1072.     dx /= delta;
  1073.     dy /= delta;
  1074.     for(i = 0; i <= delta; i++) {
  1075.       PWDrawPoint(w, (Position) x, (Position) y, value);
  1076.       x += dx;
  1077.       y += dy;
  1078.     }
  1079.   }
  1080.   else
  1081.     PWDrawPoint(w, from_x, from_y, value);
  1082. }
  1083.  
  1084. #if NeedFunctionPrototypes
  1085. void PWBlindLine(Widget w, Position from_x, Position from_y, 
  1086.          Position to_x, Position to_y, int value)
  1087. #else
  1088. void PWBlindLine(w, from_x, from_y, to_x, to_y, value)
  1089.      Widget  w;
  1090.      Position from_x, from_y, to_x, to_y;
  1091.      int value;
  1092. #endif
  1093. {
  1094.   Position i;
  1095.   register double x, y;
  1096.   double dx, dy, delta;
  1097.   
  1098.   dx = to_x - from_x;
  1099.   dy = to_y - from_y;
  1100.   x = from_x + 0.5;
  1101.   y = from_y + 0.5;
  1102.   delta = max(abs(dx), abs(dy));
  1103.   if (delta > 0) {
  1104.     dx /= delta;
  1105.     dy /= delta;
  1106.     x += dx;
  1107.     y += dy;
  1108.     for(i = 1; i <= delta; i++) {
  1109.       PWDrawPoint(w, (Position) x, (Position) y, value);
  1110.       x += dx;
  1111.       y += dy;
  1112.     }
  1113.   }
  1114.   else
  1115.     PWDrawPoint(w, from_x, from_y, value);
  1116. }
  1117.  
  1118. #if NeedFunctionPrototypes
  1119. void PWDrawRectangle(Widget w, Position from_x, Position from_y, 
  1120.              Position to_x, Position to_y, int value)
  1121. #else
  1122. void PWDrawRectangle(w, from_x, from_y, to_x, to_y, value)
  1123.      Widget w;
  1124.      Position from_x, from_y, to_x, to_y;
  1125.      int value;
  1126. #endif
  1127. {
  1128.   register Position i;
  1129.   Dimension delta, width, height;
  1130.   
  1131.   QuerySwap(from_x, to_x);
  1132.   QuerySwap(from_y, to_y);
  1133.   
  1134.   width = to_x - from_x;
  1135.   height = to_y - from_y;
  1136.   
  1137.   delta = max(width, height);
  1138.   
  1139.   if (!QueryZero(width, height)) {
  1140.     for (i = 0; i < delta; i++) {
  1141.       if (i < width) {
  1142.     PWDrawPoint(w, from_x + i, from_y, value);
  1143.     PWDrawPoint(w, to_x - i, to_y, value);
  1144.       }
  1145.       if (i < height) {
  1146.     PWDrawPoint(w, from_x, to_y - i, value);
  1147.     PWDrawPoint(w, to_x, from_y + i, value);
  1148.       }
  1149.     }
  1150.   }
  1151.   else
  1152.     PWDrawLine(w, 
  1153.            from_x, from_y, 
  1154.            to_x, to_y, value);
  1155. }
  1156.  
  1157. #if NeedFunctionPrototypes
  1158. void PWDrawFilledRectangle(Widget w, Position from_x, Position from_y, 
  1159.                Position to_x, Position to_y, int value)
  1160. #else
  1161. void PWDrawFilledRectangle(w, from_x, from_y, to_x, to_y, value)
  1162.      Widget w;
  1163.      Position from_x, from_y, to_x, to_y;
  1164.      int value;
  1165. #endif
  1166. {
  1167.   register Position x, y;
  1168.   
  1169.   QuerySwap(from_x, to_x);
  1170.   QuerySwap(from_y, to_y);
  1171.   
  1172.   for (x = from_x; x <= to_x; x++)
  1173.     for (y = from_y; y <= to_y; y++)
  1174.       PWDrawPoint(w, x, y, value);
  1175. }
  1176.  
  1177. #if NeedFunctionPrototypes
  1178. void PWDrawCircle(Widget w, Position origin_x, Position origin_y, 
  1179.           Position point_x, Position point_y, int value)
  1180. #else
  1181. void PWDrawCircle(w, origin_x, origin_y, point_x, point_y, value)
  1182.      Widget w;
  1183.      Position origin_x, origin_y, point_x, point_y;
  1184.      int value;
  1185. #endif
  1186. {
  1187.   register Position i, delta;
  1188.   Dimension dx, dy, half;
  1189.   double radius;
  1190.   
  1191.   dx = abs(point_x - origin_x);
  1192.   dy = abs(point_y - origin_y);
  1193.   radius = sqrt((double) (dx * dx + dy * dy));
  1194.   if (radius < 1.0) {
  1195.     PWDrawPoint(w, origin_x, origin_y, value);
  1196.   }
  1197.   else {
  1198.     PWDrawPoint(w, origin_x - (Position) floor(radius), origin_y, value);
  1199.     PWDrawPoint(w, origin_x + (Position) floor(radius), origin_y, value);
  1200.     PWDrawPoint(w, origin_x, origin_y - (Position) floor(radius), value);
  1201.     PWDrawPoint(w, origin_x, origin_y + (Position) floor(radius), value);
  1202.   }
  1203.   half = radius / sqrt(2.0);
  1204.   for(i = 1; i <= half; i++) {
  1205.     delta = sqrt(radius * radius - i * i);
  1206.     PWDrawPoint(w, origin_x - delta, origin_y - i, value);
  1207.     PWDrawPoint(w, origin_x - delta, origin_y + i, value);
  1208.     PWDrawPoint(w, origin_x + delta, origin_y - i, value);
  1209.     PWDrawPoint(w, origin_x + delta, origin_y + i, value);
  1210.     if (i != delta) {
  1211.       PWDrawPoint(w, origin_x - i, origin_y - delta, value);
  1212.       PWDrawPoint(w, origin_x - i, origin_y + delta, value);
  1213.       PWDrawPoint(w, origin_x + i, origin_y - delta, value);
  1214.       PWDrawPoint(w, origin_x + i, origin_y + delta, value);
  1215.     }
  1216.   }
  1217. }
  1218.  
  1219. #if NeedFunctionPrototypes
  1220. void PWDrawFilledCircle(Widget w, Position origin_x, Position origin_y, 
  1221.             Position point_x, Position point_y, int value)
  1222. #else
  1223. void PWDrawFilledCircle(w, origin_x, origin_y, point_x, point_y, value)
  1224.      Widget w;
  1225.      Position origin_x, origin_y, point_x, point_y;
  1226.      int value;
  1227. #endif
  1228. {
  1229.   register Position i, j, delta;
  1230.   Dimension dx, dy;
  1231.   double radius;
  1232.   
  1233.   dx = abs(point_x - origin_x);
  1234.   dy = abs(point_y - origin_y);
  1235.   radius = sqrt((double) (dx * dx + dy * dy));
  1236.   for(j = origin_x - (Position) floor(radius); 
  1237.       j <= origin_x + (Position) floor(radius); j++)
  1238.     PWDrawPoint(w, j, origin_y, value);
  1239.   for(i = 1; i <= (Position) floor(radius); i++) {
  1240.     delta = sqrt(radius * radius - i * i);
  1241.     for(j = origin_x - delta; j <= origin_x + delta; j++) {
  1242.       PWDrawPoint(w, j, origin_y - i, value);
  1243.       PWDrawPoint(w, j, origin_y + i, value);
  1244.     }
  1245.   }
  1246. }
  1247.  
  1248.  
  1249. #if NeedFunctionPrototypes
  1250. void PWFloodFill(Widget w, Position x, Position y, int value)
  1251. #else
  1252. void PWFloodFill(w, x, y, value)
  1253.      Widget w;
  1254.      Position x, y;
  1255.      int value;
  1256. #endif
  1257. {
  1258.   PixmapWidget PW = (PixmapWidget) w;
  1259.   Pixel pixel, foreground = PW->pixmap.foreground_pixel;
  1260.   Pixel clear = PW->pixmap.clear_pixel;
  1261.   
  1262.   pixel = GetPxl(PW, x, y);
  1263.   
  1264.   if (value == Invert)
  1265.     FloodLoop(PW, x, y, ((pixel != clear) ? clear : foreground), pixel);
  1266.   else if (value == Clear)
  1267.     FloodLoop(PW, x, y, clear, pixel);
  1268.   else
  1269.     FloodLoop(PW, x, y, foreground, pixel); 
  1270. }
  1271.  
  1272. #if NeedFunctionPrototypes
  1273. void PWUp(Widget w)
  1274. #else
  1275. void PWUp(w)
  1276.      Widget w;
  1277. #endif
  1278. {
  1279.   PixmapWidget PW = (PixmapWidget) w;
  1280.   register Position x, y;
  1281.   Pixel first, up, down;
  1282.   Position from_x, from_y, to_x, to_y;
  1283.   
  1284.   if (PWQueryMarked(w)) {
  1285.     from_x = PW->pixmap.mark.from_x;
  1286.     from_y = PW->pixmap.mark.from_y;
  1287.     to_x = PW->pixmap.mark.to_x;
  1288.     to_y = PW->pixmap.mark.to_y;
  1289.   }
  1290.   else {
  1291.     from_x = 0;
  1292.     from_y = 0;
  1293.     to_x = PW->pixmap.width - 1;
  1294.     to_y = PW->pixmap.height - 1;
  1295.   }
  1296.   
  1297.   if ((to_y - from_y) == 0)
  1298.     return;
  1299.   
  1300.   for(x = from_x; x <= to_x; x++) {
  1301.     first = up = GetPxl(PW, x, to_y);
  1302.     for(y = to_y - 1; y >= from_y; y--) {
  1303.       down = GetPxl(PW, x, y);
  1304.       if (up != down) 
  1305.     {
  1306.       DrawPoint(PW, x, y, up, Lazy);
  1307.     }
  1308.       up = down;
  1309.     }
  1310.     if (first != down)
  1311.       {
  1312.     DrawPoint(PW, x, to_y, down, Lazy);
  1313.       }
  1314.   }
  1315.   
  1316.   if (!PWQueryMarked(w)) {
  1317.       if (QuerySet(PW->pixmap.hot.x, PW->pixmap.hot.y)) {
  1318.           PWSetHotSpot(w,
  1319.                PW->pixmap.hot.x,
  1320.                (PW->pixmap.hot.y - 1 + PW->pixmap.image->height) % 
  1321.                PW->pixmap.image->height);
  1322.       }
  1323.       if (PW->pixmap.translateCallback) 
  1324.           PW->pixmap.translateCallback( w, 0, -1 );
  1325.   }
  1326. }
  1327.  
  1328. #if NeedFunctionPrototypes
  1329. void PWDown(Widget w)
  1330. #else
  1331. void PWDown(w)
  1332.      Widget w;
  1333. #endif
  1334. {
  1335.   PixmapWidget PW = (PixmapWidget) w;
  1336.   register Position x, y;
  1337.   Pixel first, down, up;
  1338.   Position from_x, from_y, to_x, to_y;
  1339.   
  1340.   if (PWQueryMarked(w)) {
  1341.     from_x = PW->pixmap.mark.from_x;
  1342.     from_y = PW->pixmap.mark.from_y;
  1343.     to_x = PW->pixmap.mark.to_x;
  1344.     to_y = PW->pixmap.mark.to_y;
  1345.   }
  1346.   else {
  1347.     from_x = 0;
  1348.     from_y = 0;
  1349.     to_x = PW->pixmap.width - 1;
  1350.     to_y = PW->pixmap.height - 1;
  1351.   }
  1352.   
  1353.   if ((to_y - from_y) == 0)
  1354.     return;
  1355.   
  1356.   for(x = from_x; x <= to_x; x++) {
  1357.     first = down = GetPxl(PW, x, from_y);
  1358.     for(y = from_y + 1; y <= to_y; y++) {
  1359.       up = GetPxl(PW, x, y);
  1360.       if (down != up)
  1361.     {
  1362.       DrawPoint(PW, x, y, down, Lazy);
  1363.     }
  1364.       down = up;
  1365.     }
  1366.     if(first != up) 
  1367.       {
  1368.     DrawPoint(PW, x, from_y, up, Lazy);
  1369.       }
  1370.   }
  1371.   
  1372.   if (!PWQueryMarked(w)) {
  1373.       if (QuerySet(PW->pixmap.hot.x, PW->pixmap.hot.y)) {
  1374.           PWSetHotSpot(w,
  1375.                PW->pixmap.hot.x,
  1376.                (PW->pixmap.hot.y + 1) % PW->pixmap.image->height);
  1377.       }
  1378.       if (PW->pixmap.translateCallback) 
  1379.           PW->pixmap.translateCallback( w, 0, 1 );
  1380.   }
  1381. }
  1382.  
  1383. #if NeedFunctionPrototypes
  1384. void PWLeft(Widget w)
  1385. #else
  1386. void PWLeft(w)
  1387.      Widget w;
  1388. #endif
  1389. {
  1390.   PixmapWidget PW = (PixmapWidget) w;
  1391.   register Position x, y;
  1392.   Pixel first, left, right;
  1393.   Position from_x, from_y, to_x, to_y;
  1394.   
  1395.   if (PWQueryMarked(w)) {
  1396.     from_x = PW->pixmap.mark.from_x;
  1397.     from_y = PW->pixmap.mark.from_y;
  1398.     to_x = PW->pixmap.mark.to_x;
  1399.     to_y = PW->pixmap.mark.to_y;
  1400.   }
  1401.   else {
  1402.     from_x = 0;
  1403.     from_y = 0;
  1404.     to_x = PW->pixmap.width - 1;
  1405.     to_y = PW->pixmap.height - 1;
  1406.   }
  1407.   
  1408.   if ((to_x - from_x) == 0)
  1409.     return;
  1410.   
  1411.   for(y = from_y; y <= to_y; y++) {
  1412.     first = left = GetPxl(PW, to_x, y);
  1413.     for(x = to_x - 1; x >= from_x; x--) {
  1414.       right = GetPxl(PW, x, y);
  1415.       if (left != right)
  1416.     {
  1417.       DrawPoint(PW, x, y, left, Lazy);
  1418.     }
  1419.       left = right;
  1420.     }
  1421.     if(first != right)
  1422.       {
  1423.     DrawPoint(PW, to_x, y, right, Lazy);
  1424.       }
  1425.   }
  1426.  
  1427.   if (!PWQueryMarked(w)) {
  1428.       if (QuerySet(PW->pixmap.hot.x, PW->pixmap.hot.y)) {
  1429.           PWSetHotSpot(w,
  1430.                (PW->pixmap.hot.x - 1 + PW->pixmap.image->width) % 
  1431.                    PW->pixmap.image->width,
  1432.                PW->pixmap.hot.y);
  1433.       }
  1434.       if (PW->pixmap.translateCallback) 
  1435.           PW->pixmap.translateCallback( w, -1, 0 );
  1436.   }
  1437. }
  1438.  
  1439. #if NeedFunctionPrototypes
  1440. void PWRight(Widget w)
  1441. #else
  1442. void PWRight(w)
  1443.      Widget w;
  1444. #endif
  1445. {
  1446.   PixmapWidget PW = (PixmapWidget) w;
  1447.   register Position x, y;
  1448.   Pixel first, right, left;
  1449.   Position from_x, from_y, to_x, to_y;
  1450.   
  1451.   if (PWQueryMarked(w)) {
  1452.     from_x = PW->pixmap.mark.from_x;
  1453.     from_y = PW->pixmap.mark.from_y;
  1454.     to_x = PW->pixmap.mark.to_x;
  1455.     to_y = PW->pixmap.mark.to_y;
  1456.   }
  1457.   else {
  1458.     from_x = 0;
  1459.     from_y = 0;
  1460.     to_x = PW->pixmap.width - 1;
  1461.     to_y = PW->pixmap.height - 1;
  1462.   }
  1463.   
  1464.   if ((to_x - from_x) == 0)
  1465.     return;
  1466.   
  1467.   for(y = from_y; y <= to_y; y++) {
  1468.     first = right = GetPxl(PW, from_x, y);
  1469.     for(x = from_x + 1; x <= to_x; x++) {
  1470.       left = GetPxl(PW, x, y);
  1471.       if (right != left)
  1472.     {
  1473.       DrawPoint(PW, x, y, right, Lazy);
  1474.     }
  1475.       right = left;
  1476.     }
  1477.     if(first != left)
  1478.       {
  1479.     DrawPoint(PW, from_x, y, left, Lazy);
  1480.       }
  1481.   }
  1482.  
  1483.   if (!PWQueryMarked(w)) {
  1484.       if (QuerySet(PW->pixmap.hot.x, PW->pixmap.hot.y)) {
  1485.           PWSetHotSpot(w,
  1486.                (PW->pixmap.hot.x + 1) % PW->pixmap.image->width,
  1487.                PW->pixmap.hot.y);
  1488.       }
  1489.       if (PW->pixmap.translateCallback) 
  1490.           PW->pixmap.translateCallback( w, 1, 0 );
  1491.   }
  1492. }
  1493.  
  1494. #if NeedFunctionPrototypes
  1495. void PWRedrawMark(Widget w)
  1496. #else
  1497. void PWRedrawMark(w)
  1498.      Widget w;
  1499. #endif
  1500. {
  1501.   PixmapWidget PW = (PixmapWidget) w;
  1502.   
  1503.   if (QuerySet(PW->pixmap.mark.from_x, PW->pixmap.mark.from_y)) 
  1504.     XFillRectangle(dpy, XtWindow(PW), PW->pixmap.highlighting_gc,
  1505.            InWindowX(PW, PW->pixmap.mark.from_x), 
  1506.            InWindowY(PW, PW->pixmap.mark.from_y), 
  1507.            InWindowX(PW, PW->pixmap.mark.to_x + 1) - 
  1508.            InWindowX(PW, PW->pixmap.mark.from_x),
  1509.            InWindowY(PW, PW->pixmap.mark.to_y + 1) -
  1510.            InWindowY(PW, PW->pixmap.mark.from_y));
  1511. }
  1512.  
  1513. #if NeedFunctionPrototypes
  1514. void PWFold(Widget w)
  1515. #else
  1516. void PWFold(w)
  1517.      Widget w;
  1518. #endif
  1519. {
  1520.   PixmapWidget PW = (PixmapWidget) w;
  1521.   Position x, y, new_x, new_y;
  1522.   Dimension horiz, vert;
  1523.   XImage *storage, *mask_storage;
  1524.   Pixel color;
  1525.   
  1526.   storage = CreatePixmapImage(PW, (Dimension) PW->pixmap.image->width, 
  1527.                   (Dimension) PW->pixmap.image->height);
  1528.   mask_storage = CreateMaskImage(PW, (Dimension) PW->pixmap.mask_image->width, 
  1529.                  (Dimension) PW->pixmap.mask_image->height);
  1530.   
  1531.   TransferImageData(PW->pixmap.image, storage);
  1532.   TransferImageData(PW->pixmap.mask_image, mask_storage);
  1533.   
  1534.   PW->pixmap.fold ^= True;
  1535.   horiz = (PW->pixmap.image->width + PW->pixmap.fold) / 2;
  1536.   vert = (PW->pixmap.image->height + PW->pixmap.fold) / 2;
  1537.   
  1538.   for (x = 0; x < PW->pixmap.image->width; x++)
  1539.     for (y = 0; y < PW->pixmap.image->height; y++) {
  1540.       new_x = (x + horiz) % PW->pixmap.image->width;
  1541.       new_y = (y + vert) % PW->pixmap.image->height;
  1542.       if(GetPxl(PW, new_x, new_y) != 
  1543.      (color = GetPxlFromImageAndMask(storage, mask_storage, x, y)))
  1544.     {
  1545.       DrawPoint(PW, new_x, new_y, color, Lazy);
  1546.     }
  1547.     }
  1548.   
  1549.   DestroyPixmapImage(&storage);
  1550.   DestroyMaskImage(&mask_storage);
  1551.   
  1552.   if (QuerySet(PW->pixmap.hot.x, PW->pixmap.hot.y))
  1553.     PWSetHotSpot(w, 
  1554.          (Position) 
  1555.          ((PW->pixmap.hot.x + horiz) % PW->pixmap.image->width),
  1556.          (Position)
  1557.          ((PW->pixmap.hot.y + vert) % PW->pixmap.image->height));
  1558.   if (PW->pixmap.translateCallback) 
  1559.       PW->pixmap.translateCallback( w, horiz, vert );
  1560. }
  1561.  
  1562. #if NeedFunctionPrototypes
  1563. void PWClear(Widget w)
  1564. #else
  1565. void PWClear(w)
  1566.      Widget w;
  1567. #endif
  1568. {
  1569.   PixmapWidget PW = (PixmapWidget) w;
  1570.   register Position x, y;
  1571.   register Position from_x, from_y, to_x, to_y;
  1572.   
  1573.   if (PWQueryMarked(w)) {
  1574.     from_x = PW->pixmap.mark.from_x;
  1575.     from_y = PW->pixmap.mark.from_y;
  1576.     to_x = PW->pixmap.mark.to_x;
  1577.     to_y = PW->pixmap.mark.to_y;
  1578.   }
  1579.   else {
  1580.     from_x = 0;
  1581.     from_y = 0;
  1582.     to_x = PW->pixmap.image->width - 1;
  1583.     to_y = PW->pixmap.image->height - 1;
  1584.   }
  1585.   for (x = from_x; x <= to_x; x++)
  1586.     for (y = from_y; y <= to_y; y++)
  1587.       ClearPoint(PW, x, y, Lazy);
  1588. /* This way is too flashy
  1589.       ClearPxl(PW->pixmap.image, x, y, PW->pixmap.clear_pixel);
  1590.   XClearArea(dpy, XtWindow(PW),
  1591.          0, 0, PW->core.width, PW->core.height, True);*/
  1592.  
  1593. }
  1594.  
  1595. #if NeedFunctionPrototypes
  1596. void PWSet(Widget w)
  1597. #else
  1598. void PWSet(w)
  1599.      Widget w;
  1600. #endif
  1601. {
  1602.   PixmapWidget PW = (PixmapWidget) w;
  1603.   register Position x, y;
  1604.   register Position from_x, from_y, to_x, to_y;
  1605.   
  1606.   if (PWQueryMarked(w)) {
  1607.     from_x = PW->pixmap.mark.from_x;
  1608.     from_y = PW->pixmap.mark.from_y;
  1609.     to_x = PW->pixmap.mark.to_x;
  1610.     to_y = PW->pixmap.mark.to_y;
  1611.   }
  1612.   else {
  1613.     from_x = 0;
  1614.     from_y = 0;
  1615.     to_x = PW->pixmap.image->width - 1;
  1616.     to_y = PW->pixmap.image->height - 1;
  1617.   }
  1618.   for (x = from_x; x <= to_x; x++)
  1619.     for (y = from_y; y <= to_y; y++)
  1620.       {
  1621.     DrawPoint(PW, x, y, PW->pixmap.foreground_pixel, Lazy);
  1622.       }
  1623.  
  1624. }
  1625.  
  1626. #if NeedFunctionPrototypes
  1627. void PWRedraw(Widget w)
  1628. #else
  1629. void PWRedraw(w)
  1630.      Widget w;
  1631. #endif
  1632. {
  1633.   PixmapWidget PW = (PixmapWidget) w;
  1634.   
  1635.   XClearArea(dpy, XtWindow(PW),
  1636.          0, 0, PW->core.width, PW->core.height,
  1637.          True);
  1638. }
  1639.  
  1640.  
  1641. /*--------------------------------------------------------------------------*/
  1642. /*
  1643.             P W T r a n s l a t e P o i n t
  1644.  
  1645.     Translate a point by dx, dy wrapping around if the point goes off
  1646.     the pixmap
  1647. */
  1648. /*--------------------------------------------------------------------------*/
  1649. void PWTranslatePoint( w, x, y, dx, dy )
  1650.     Widget    w;
  1651.     Position    *x;
  1652.     Position    *y;
  1653.     Position    dx;
  1654.     Position    dy;
  1655. {
  1656.     PixmapWidget PW = (PixmapWidget) w;
  1657. /*
  1658.     printf("PWTranslatePoint : %d,%d by %d,%d\n", *x, *y, dx, dy);
  1659. */
  1660.     *x = (*x + dx + PW->pixmap.image->width)  % PW->pixmap.image->width;
  1661.     *y = (*y + dy + PW->pixmap.image->height) % PW->pixmap.image->height;
  1662. }
  1663.  
  1664.  
  1665. /*--------------------------------------------------------------------------*/
  1666. /*
  1667.                         P W F l i p P o i n t
  1668.  
  1669.         Flip a given point guaranteeing that the flipped point will be
  1670.         in the pixmap.
  1671. */
  1672. /*--------------------------------------------------------------------------*/
  1673.  
  1674. void PWFlipPoint( w, x, y, axis )
  1675.     Widget          w;
  1676.     Position        *x;
  1677.     Position        *y;
  1678.     enum FlipAxis   axis;
  1679. {
  1680.     PixmapWidget PW = (PixmapWidget) w;
  1681.  
  1682.     if ( axis == Vertical ) 
  1683.         *x = PW->pixmap.image->width  - 1 - *x;
  1684.     else 
  1685.         *y = PW->pixmap.image->height - 1 - *y;
  1686. }
  1687.  
  1688.  
  1689. /*--------------------------------------------------------------------------*/
  1690. /*
  1691.                         R o t a t e P o i n t
  1692.  
  1693.         Rotate a single point left or right 90 degrees. Guarantee that
  1694.         result is in pixmap.
  1695. */
  1696. /*--------------------------------------------------------------------------*/
  1697.  
  1698. void PWRotatePoint( w, x, y, direction )
  1699.     Widget                      w;
  1700.     Position                    *x;
  1701.     Position                    *y;
  1702.     enum RotateDirection        direction;
  1703. {
  1704.     PixmapWidget PW = (PixmapWidget) w;
  1705.  
  1706.     Position from_x, from_y, to_x, to_y;
  1707.     Position half_width, half_height, shift;
  1708.     Position tmp;
  1709.  
  1710.     if (PWQueryMarked(w)) {
  1711.       from_x = PW->pixmap.mark.from_x;
  1712.       from_y = PW->pixmap.mark.from_y;
  1713.       to_x   = PW->pixmap.mark.to_x;
  1714.       to_y   = PW->pixmap.mark.to_y;
  1715.     }
  1716.     else {
  1717.       from_x = 0;
  1718.       from_y = 0;
  1719.       to_x   = PW->pixmap.width - 1;
  1720.       to_y   = PW->pixmap.height - 1;
  1721.     }
  1722.     half_width = floor((to_x - from_x) / 2.0 + 0.5);
  1723.     half_height= floor((to_y - from_y ) / 2.0 + 0.5);
  1724.     shift      = min((Position)(to_x - from_x), (Position)(to_y - from_y )) % 2;
  1725.  
  1726.     *x -= half_width;
  1727.     *y -= half_height;
  1728.     if (*x >= 0) *x += shift;
  1729.     if (*y >= 0) *y += shift;
  1730.     tmp = *x;
  1731.     if (direction == Right) {
  1732.         *x = - *y;
  1733.         *y = tmp;
  1734.     } else {
  1735.         *x = *y;
  1736.         *y = - tmp;
  1737.     }
  1738.     if (*x > 0) *x -= shift;
  1739.     if (*y > 0) *y -= shift;
  1740.     *x += half_width;
  1741.     *y += half_height;
  1742. }
  1743.  
  1744.  
  1745. #if NeedFunctionPrototypes
  1746. void PWFlipHoriz(Widget w)
  1747. #else
  1748. void PWFlipHoriz(w)
  1749.      Widget w;
  1750. #endif
  1751. {
  1752.   PixmapWidget PW = (PixmapWidget) w;
  1753.   register Position x, y;
  1754.   Position from_x, from_y, to_x, to_y;
  1755.   XPoint hot;
  1756.   float half;
  1757.   Pixel color1, color2;
  1758.   
  1759.   if (PWQueryMarked(w)) {
  1760.     from_x = PW->pixmap.mark.from_x;
  1761.     from_y = PW->pixmap.mark.from_y;
  1762.     to_x = PW->pixmap.mark.to_x;
  1763.     to_y = PW->pixmap.mark.to_y;
  1764.   }
  1765.   else {
  1766.     from_x = 0;
  1767.     from_y = 0;
  1768.     to_x = PW->pixmap.width - 1;
  1769.     to_y = PW->pixmap.height - 1;
  1770.   }
  1771.   half = (float) (to_y - from_y) / 2.0 + 0.5;
  1772.   
  1773.   if (half == 0.0)
  1774.     return;
  1775.   
  1776.   for (x = from_x; x <= to_x; x++) 
  1777.     for (y = 0; y <  half; y++)
  1778.       if ((color1 = GetPxl(PW, x, from_y + y)) != 
  1779.       (color2 = GetPxl(PW, x, to_y - y))) {
  1780.     DrawPoint(PW, x, from_y + y, color2, Lazy);
  1781.     DrawPoint(PW, x, to_y - y, color1, Lazy);
  1782.       }
  1783.  
  1784.   if (!PWQueryMarked(w)) {
  1785.       if (QuerySet(PW->pixmap.hot.x, PW->pixmap.hot.y)) {
  1786.           hot.x = PW->pixmap.hot.x;
  1787.           hot.y = PW->pixmap.hot.y;
  1788.           PWFlipPoint( w, &hot.x, &hot.y, Horizontal ); 
  1789.           PWSetHotSpot(w, hot.x, hot.y );
  1790.       }
  1791.       /* flip extensions */
  1792.       if (PW->pixmap.flipCallback) 
  1793.           PW->pixmap.flipCallback( w, Horizontal );
  1794.   }
  1795. }
  1796.  
  1797.  
  1798. #if NeedFunctionPrototypes
  1799. void PWFlipVert(Widget w)
  1800. #else
  1801. void PWFlipVert(w)
  1802.      Widget w;
  1803. #endif
  1804. {
  1805.   PixmapWidget PW = (PixmapWidget) w;
  1806.   register Position x, y;
  1807.   Position from_x, from_y, to_x, to_y;
  1808.   XPoint hot;
  1809.   float half;
  1810.   Pixel color1, color2;
  1811.   
  1812.   if (PWQueryMarked(w)) {
  1813.     from_x = PW->pixmap.mark.from_x;
  1814.     from_y = PW->pixmap.mark.from_y;
  1815.     to_x = PW->pixmap.mark.to_x;
  1816.     to_y = PW->pixmap.mark.to_y;
  1817.   }
  1818.   else {
  1819.     from_x = 0;
  1820.     from_y = 0;
  1821.     to_x = PW->pixmap.width - 1;
  1822.     to_y = PW->pixmap.height - 1;
  1823.   }
  1824.   half = (float) (to_x - from_x) / 2.0 + 0.5;
  1825.   
  1826.   if (half == 0)
  1827.     return;
  1828.   
  1829.   for (y = from_y; y <= to_y; y++)
  1830.     for (x = 0; x < half; x++)
  1831.       if ((color1 = GetPxl(PW, from_x + x, y)) != 
  1832.       (color2 = GetPxl(PW, to_x - x, y))) {
  1833.     DrawPoint(PW, from_x + x, y, color2, Lazy);
  1834.     DrawPoint(PW, to_x - x, y, color1, Lazy);
  1835.       }
  1836.  
  1837.   if (!PWQueryMarked(w)) {
  1838.       if (QuerySet(PW->pixmap.hot.x, PW->pixmap.hot.y)) {
  1839.           hot.x = PW->pixmap.hot.x;
  1840.           hot.y = PW->pixmap.hot.y;
  1841.           PWFlipPoint( w, &hot.x, &hot.y, Vertical ); 
  1842.           PWSetHotSpot(w, hot.x, hot.y );
  1843.       }
  1844.       /* flip extensions */
  1845.       if (PW->pixmap.flipCallback) 
  1846.           PW->pixmap.flipCallback( w, Vertical );
  1847.   }
  1848. }
  1849.  
  1850.  
  1851. #if NeedFunctionPrototypes
  1852. void PWRotateRight(Widget w)
  1853. #else
  1854. void PWRotateRight(w)
  1855.      Widget w;
  1856. #endif
  1857. {
  1858.   PixmapWidget PW = (PixmapWidget) w;
  1859.   Position x, y, delta, shift, tmp;
  1860.   Position half_width, half_height;
  1861.   XPoint hot;
  1862.   Pixel quad1, quad2, quad3, quad4;
  1863.   Position from_x, from_y, to_x, to_y;
  1864.   
  1865.   if (PWQueryMarked(w)) {
  1866.     from_x = PW->pixmap.mark.from_x;
  1867.     from_y = PW->pixmap.mark.from_y;
  1868.     to_x = PW->pixmap.mark.to_x;
  1869.     to_y = PW->pixmap.mark.to_y;
  1870.   }
  1871.   else {
  1872.     from_x = 0;
  1873.     from_y = 0;
  1874.     to_x = PW->pixmap.width - 1;
  1875.     to_y = PW->pixmap.height - 1;
  1876.   }
  1877.   
  1878.   half_width = floor((to_x - from_x) / 2.0 + 0.5);
  1879.   half_height = floor((to_y - from_y ) / 2.0 + 0.5);
  1880.   shift = min((Position)(to_x - from_x), (Position)(to_y - from_y )) % 2;
  1881.   delta = min((Position) half_width, (Position) half_height) - shift;
  1882.   
  1883.   for (x = 0; x <= delta; x++) {
  1884.     for (y = 1 - shift; y <= delta; y++) {
  1885.       quad1 = GetPxl(PW, 
  1886.              from_x + (Position)half_width + x, 
  1887.              from_y + (Position)half_height + y);
  1888.       quad2 = GetPxl(PW, 
  1889.              from_x + (Position)half_width + y, 
  1890.              from_y + (Position)half_height - shift - x);
  1891.       quad3 = GetPxl(PW, 
  1892.              from_x + (Position)half_width - shift - x, 
  1893.              from_y + (Position)half_height - shift - y);
  1894.       quad4 = GetPxl(PW, 
  1895.              from_x + (Position)half_width - shift - y, 
  1896.              from_y + (Position)half_height + x);
  1897.       
  1898.       if (quad1 != quad2)
  1899.     {
  1900.       DrawPoint(PW, from_x + (Position)half_width + x, 
  1901.             from_y + (Position)half_height + y, quad2, Lazy);
  1902.     }
  1903.       if (quad2 != quad3)
  1904.     {
  1905.       DrawPoint(PW, from_x + (Position)half_width + y, 
  1906.             from_y + (Position)half_height - shift - x, quad3, Lazy);
  1907.     }
  1908.       if (quad3 != quad4)
  1909.     {
  1910.       DrawPoint(PW, from_x + (Position)half_width - shift - x,
  1911.             from_y + (Position)half_height - shift - y, quad4, Lazy);
  1912.     }
  1913.       if (quad4 != quad1)
  1914.     {
  1915.       DrawPoint(PW, from_x + (Position)half_width - shift - y, 
  1916.             from_y + (Position)half_height + x, quad1, Lazy);
  1917.     }
  1918.     }
  1919.   }
  1920.   
  1921.   if (!PWQueryMarked(w)) {
  1922.       if (QuerySet(PW->pixmap.hot.x, PW->pixmap.hot.y)) {
  1923.           hot.x = PW->pixmap.hot.x;
  1924.           hot.y = PW->pixmap.hot.y;
  1925.           PWRotatePoint( w, &hot.x, &hot.y, Right ); 
  1926.           if (QueryInPixmap(PW, hot.x, hot.y))
  1927.             PWSetHotSpot(w, hot.x, hot.y);
  1928.       }
  1929.       /* rotate extensions */
  1930.       if (PW->pixmap.rotateCallback) 
  1931.           PW->pixmap.rotateCallback( w, Right );
  1932.   }
  1933. }
  1934.  
  1935.  
  1936. #if NeedFunctionPrototypes
  1937. void PWRotateLeft(Widget w)
  1938. #else
  1939. void PWRotateLeft(w)
  1940.      Widget w;
  1941. #endif
  1942. {
  1943.   PixmapWidget PW = (PixmapWidget) w;
  1944.   Position x, y,delta, shift, tmp;
  1945.   Position half_width, half_height;
  1946.   XPoint hot;
  1947.   Pixel quad1, quad2, quad3, quad4;
  1948.   Position from_x, from_y, to_x, to_y;
  1949.   
  1950.   if (PWQueryMarked(w)) {
  1951.     from_x = PW->pixmap.mark.from_x;
  1952.     from_y = PW->pixmap.mark.from_y;
  1953.     to_x = PW->pixmap.mark.to_x;
  1954.     to_y = PW->pixmap.mark.to_y;
  1955.   }
  1956.   else {
  1957.     from_x = 0;
  1958.     from_y = 0;
  1959.     to_x = PW->pixmap.width - 1;
  1960.     to_y = PW->pixmap.height - 1;
  1961.   }
  1962.   
  1963.   half_width = floor((to_x - from_x) / 2.0 + 0.5);
  1964.   half_height = floor((to_y - from_y ) / 2.0 + 0.5);
  1965.   shift = min((Position)(to_x - from_x), (Position)(to_y - from_y )) % 2;
  1966.   delta = min((Position) half_width, (Position) half_height) - shift;
  1967.   
  1968.   for (x = 0; x <= delta; x++) {
  1969.     for (y = 1 - shift; y <= delta; y++) {
  1970.       quad1 = GetPxl(PW, 
  1971.              from_x + (Position)half_width + x, 
  1972.              from_y + (Position)half_height + y);
  1973.       quad2 = GetPxl(PW, 
  1974.              from_x + (Position)half_width + y, 
  1975.              from_y + (Position)half_height - shift - x);
  1976.       quad3 = GetPxl(PW, 
  1977.              from_x + (Position)half_width - shift - x, 
  1978.              from_y + (Position)half_height - shift - y);
  1979.       quad4 = GetPxl(PW, 
  1980.              from_x + (Position)half_width - shift - y, 
  1981.              from_y + (Position)half_height + x);
  1982.       
  1983.       if (quad1 != quad4)
  1984.     {
  1985.       DrawPoint(PW, from_x + (Position)half_width + x, 
  1986.             from_y + (Position)half_height + y, quad4, Lazy);
  1987.     }
  1988.       if (quad2 != quad1)
  1989.     {
  1990.       DrawPoint(PW, from_x + (Position)half_width + y, 
  1991.             from_y + (Position)half_height - shift - x, quad1, Lazy);
  1992.     }
  1993.       if (quad3 != quad2)
  1994.     {
  1995.       DrawPoint(PW, from_x + (Position)half_width - shift - x,
  1996.             from_y + (Position)half_height - shift - y, quad2, Lazy);
  1997.     }
  1998.       if (quad4 != quad3)
  1999.     {
  2000.       DrawPoint(PW, from_x + (Position)half_width - shift - y, 
  2001.             from_y + (Position)half_height + x, quad3, Lazy);
  2002.     }
  2003.     }
  2004.   }
  2005.  
  2006.   if (!PWQueryMarked(w)) {
  2007.       if (QuerySet(PW->pixmap.hot.x, PW->pixmap.hot.y)) {
  2008.           hot.x = PW->pixmap.hot.x;
  2009.           hot.y = PW->pixmap.hot.y;
  2010.           PWRotatePoint( w, &hot.x, &hot.y, Left ); 
  2011.           if (QueryInPixmap(PW, hot.x, hot.y))
  2012.             PWSetHotSpot(w, hot.x, hot.y);
  2013.       }
  2014.       /* rotate extensions */
  2015.       if (PW->pixmap.rotateCallback) 
  2016.           PW->pixmap.rotateCallback( w, Left );
  2017.   }
  2018. }
  2019.  
  2020.  
  2021. #if NeedFunctionPrototypes
  2022. void PWStore(Widget w)
  2023. #else
  2024. void PWStore(w)
  2025.      Widget w;
  2026. #endif
  2027. {
  2028.   PixmapWidget PW = (PixmapWidget) w;
  2029.   Dimension width, height;
  2030.   
  2031.   if (QuerySet(PW->pixmap.mark.from_x, PW->pixmap.mark.from_y)) {
  2032.     
  2033.     DestroyPixmapImage(&PW->pixmap.storage);
  2034.     DestroyMaskImage(&PW->pixmap.mask_storage);
  2035.     
  2036.     width = PW->pixmap.mark.to_x - PW->pixmap.mark.from_x + 1;
  2037.     height = PW->pixmap.mark.to_y - PW->pixmap.mark.from_y + 1;
  2038.     
  2039.     PW->pixmap.storage = CreatePixmapImage(PW, width, height);
  2040.     PW->pixmap.mask_storage = CreateMaskImage(PW, width, height);
  2041.     
  2042.     CopyImageData(PW->pixmap.image, PW->pixmap.storage,
  2043.           PW->pixmap.mark.from_x,  PW->pixmap.mark.from_y,
  2044.           PW->pixmap.mark.to_x,  PW->pixmap.mark.to_y,
  2045.           0, 0);
  2046.     
  2047.     CopyImageData(PW->pixmap.mask_image, PW->pixmap.mask_storage,
  2048.           PW->pixmap.mark.from_x,  PW->pixmap.mark.from_y,
  2049.           PW->pixmap.mark.to_x,  PW->pixmap.mark.to_y,
  2050.           0, 0);
  2051.   }
  2052. }
  2053.  
  2054. #if NeedFunctionPrototypes
  2055. void PWClearMarked(Widget w)
  2056. #else
  2057. void PWClearMarked(w)
  2058.      Widget w;
  2059. #endif
  2060. {
  2061.   PixmapWidget PW = (PixmapWidget) w;
  2062.   
  2063.   if (QuerySet(PW->pixmap.mark.from_x, PW->pixmap.mark.from_y))
  2064.     {
  2065.       Position from_x = PW->pixmap.mark.from_x, 
  2066.       from_y = PW->pixmap.mark.from_y, to_x = PW->pixmap.mark.to_x, 
  2067.       to_y = PW->pixmap.mark.to_y;
  2068.       Position x, y;
  2069.       QuerySwap(from_x, to_x);
  2070.       QuerySwap(from_y, to_y);
  2071.       
  2072.       for (x = from_x; x <= to_x; x++)
  2073.     for (y = from_y; y <= to_y; y++)
  2074.       {
  2075.         ClearPoint(PW, x, y, Lazy);
  2076.       }
  2077.     }
  2078. }
  2079.  
  2080.  
  2081. #if NeedFunctionPrototypes
  2082. void PWDragMarked(Widget w, Position at_x, Position at_y)
  2083. #else
  2084. void PWDragMarked(w, at_x, at_y)
  2085.      Widget w;
  2086.      Position     at_x, at_y;
  2087. #endif
  2088. {
  2089.   PixmapWidget PW = (PixmapWidget) w;
  2090.   
  2091.   if (QuerySet(PW->pixmap.mark.from_x, PW->pixmap.mark.from_y))
  2092.     PWDrawRectangle(w, 
  2093.             at_x, at_y, 
  2094.             at_x + PW->pixmap.mark.to_x - PW->pixmap.mark.from_x,
  2095.             at_y + PW->pixmap.mark.to_y - PW->pixmap.mark.from_y,
  2096.             Highlight);
  2097. }
  2098.  
  2099. #if NeedFunctionPrototypes
  2100. void PWDragStored(Widget w, Position at_x, Position at_y)
  2101. #else
  2102. void PWDragStored(w, at_x, at_y)
  2103.      Widget w;
  2104.      Position     at_x, at_y;
  2105. #endif
  2106. {
  2107.   PixmapWidget PW = (PixmapWidget) w;
  2108.   
  2109.   if (PW->pixmap.storage)
  2110.     PWDrawRectangle(w, 
  2111.             at_x, at_y,
  2112.             at_x + PW->pixmap.storage->width - 1,
  2113.             at_y + PW->pixmap.storage->height - 1,
  2114.             Highlight);
  2115. }
  2116.  
  2117. #if NeedFunctionPrototypes
  2118. void PWRestore(Widget w, Position at_x, Position at_y, int value)
  2119. #else
  2120. void PWRestore(w, at_x, at_y, value)
  2121.      Widget w;
  2122.      Position     at_x, at_y;
  2123.      int          value;
  2124. #endif
  2125. {
  2126.   PixmapWidget PW = (PixmapWidget) w;
  2127.   
  2128.   if (PW->pixmap.storage)
  2129.     DrawImageData(PW, PW->pixmap.storage, PW->pixmap.mask_storage,
  2130.           at_x, at_y, value, Lazy);
  2131. }
  2132.  
  2133. #if NeedFunctionPrototypes
  2134. void PWCopy(Widget w, Position at_x, Position at_y, int value)
  2135. #else
  2136. void PWCopy(w, at_x, at_y, value)
  2137.      Widget w;
  2138.      Position     at_x, at_y;
  2139.      int          value;
  2140. #endif
  2141. {
  2142.   PixmapWidget PW = (PixmapWidget) w;
  2143.   XImage *storage, *mask_storage;
  2144.   Dimension width, height;
  2145.   
  2146.   if (QuerySet(PW->pixmap.mark.from_x, PW->pixmap.mark.from_y)) {
  2147.     
  2148.     width = PW->pixmap.mark.to_x - PW->pixmap.mark.from_x + 1;
  2149.     height = PW->pixmap.mark.to_y - PW->pixmap.mark.from_y + 1;
  2150.     
  2151.     storage = CreatePixmapImage(PW, width, height);
  2152.     mask_storage = CreateMaskImage(PW, width, height);
  2153.     
  2154.     CopyImageData(PW->pixmap.image, storage,
  2155.           PW->pixmap.mark.from_x,  PW->pixmap.mark.from_y,
  2156.           PW->pixmap.mark.to_x,  PW->pixmap.mark.to_y,
  2157.           0, 0);
  2158.     CopyImageData(PW->pixmap.mask_image, mask_storage,
  2159.           PW->pixmap.mark.from_x,  PW->pixmap.mark.from_y,
  2160.           PW->pixmap.mark.to_x,  PW->pixmap.mark.to_y,
  2161.           0, 0);
  2162.     
  2163.     DrawImageData(PW, storage, mask_storage, at_x, at_y, value, NotLazy);
  2164.     
  2165.     PWMark(w, at_x, at_y,
  2166.        at_x + PW->pixmap.mark.to_x - PW->pixmap.mark.from_x,
  2167.        at_y + PW->pixmap.mark.to_y - PW->pixmap.mark.from_y); 
  2168.  
  2169.     DestroyPixmapImage(&storage);
  2170.     DestroyMaskImage(&mask_storage);
  2171.   }
  2172. }
  2173.  
  2174. #if NeedFunctionPrototypes
  2175. void PWMove(Widget w, Position at_x, Position at_y, int value)
  2176. #else
  2177. void PWMove(w, at_x, at_y, value)
  2178.      Widget   w;
  2179.      Position at_x, at_y;
  2180.      int      value;
  2181. #endif
  2182. {
  2183.   PixmapWidget PW = (PixmapWidget) w;
  2184.   XImage *storage, *mask_storage;
  2185.   Dimension width, height;
  2186.   
  2187.   if (QuerySet(PW->pixmap.mark.from_x, PW->pixmap.mark.from_y)) {
  2188.     
  2189.     width = PW->pixmap.mark.to_x - PW->pixmap.mark.from_x + 1;
  2190.     height = PW->pixmap.mark.to_y - PW->pixmap.mark.from_y + 1;
  2191.     
  2192.     storage = CreatePixmapImage(PW, width, height);
  2193.     mask_storage = CreateMaskImage(PW, width, height);
  2194.     
  2195.     CopyImageData(PW->pixmap.image, storage,
  2196.           PW->pixmap.mark.from_x,  PW->pixmap.mark.from_y,
  2197.           PW->pixmap.mark.to_x,  PW->pixmap.mark.to_y,
  2198.           0, 0);
  2199.     
  2200.     CopyImageData(PW->pixmap.mask_image, mask_storage,
  2201.           PW->pixmap.mark.from_x,  PW->pixmap.mark.from_y,
  2202.           PW->pixmap.mark.to_x,  PW->pixmap.mark.to_y,
  2203.           0, 0);
  2204.     
  2205.     PWClearMarked(w);
  2206.  
  2207.     DrawImageData(PW, storage, mask_storage, at_x, at_y, value, NotLazy); 
  2208.     
  2209.     PWMark(w, at_x, at_y,
  2210.        at_x + PW->pixmap.mark.to_x - PW->pixmap.mark.from_x,
  2211.        at_y + PW->pixmap.mark.to_y - PW->pixmap.mark.from_y);
  2212.  
  2213.     DestroyPixmapImage(&storage);
  2214.     DestroyMaskImage(&mask_storage);
  2215.   }
  2216. }
  2217.  
  2218. #if NeedFunctionPrototypes
  2219. void PWStoreToBuffer(Widget w)
  2220. #else
  2221. void PWStoreToBuffer(w)
  2222.      Widget w;
  2223. #endif
  2224. {
  2225.   PixmapWidget PW = (PixmapWidget) w;
  2226.   
  2227.   /* first check available space and resize if necessary */
  2228.   if ((PW->pixmap.image->width != PW->pixmap.buffer->width) ||
  2229.       (PW->pixmap.image->height != PW->pixmap.buffer->height))
  2230.     {
  2231.       XImage *buffer = CreatePixmapImage(PW, PW->pixmap.image->width, 
  2232.                      PW->pixmap.image->height);
  2233.       XImage *mask_buffer = CreateMaskImage(PW, PW->pixmap.mask_image->width, 
  2234.                         PW->pixmap.mask_image->height);
  2235.       
  2236.       DestroyPixmapImage(&PW->pixmap.buffer);
  2237.       DestroyMaskImage(&PW->pixmap.mask_buffer);
  2238.       PW->pixmap.buffer = buffer;
  2239.       PW->pixmap.mask_buffer = mask_buffer;
  2240.     }
  2241.   
  2242.   CopyImageData(PW->pixmap.image, PW->pixmap.buffer, 0, 0, 
  2243.         PW->pixmap.image->width-1, PW->pixmap.image->height-1, 0, 0);
  2244.   CopyImageData(PW->pixmap.mask_image, PW->pixmap.mask_buffer, 0, 0, 
  2245.         PW->pixmap.mask_image->width-1,
  2246.         PW->pixmap.mask_image->height-1, 0, 0);
  2247.   
  2248.   PW->pixmap.buffer_hot  = PW->pixmap.hot;
  2249.   PW->pixmap.buffer_mark = PW->pixmap.mark;
  2250.  
  2251.   /* save extensions to undo buffer */
  2252.   XpmFreeExtensions( PW->pixmap.buffer_extensions, 
  2253.                      PW->pixmap.buffer_nextensions );
  2254.   CopyExtensions( &PW->pixmap.buffer_extensions, 
  2255.                   &PW->pixmap.buffer_nextensions,
  2256.                    PW->pixmap.extensions,
  2257.                    PW->pixmap.nextensions );
  2258. }
  2259.  
  2260. #if NeedFunctionPrototypes
  2261. void PWUnmark(Widget w)
  2262. #else
  2263. void PWUnmark(w)
  2264.      Widget w;
  2265. #endif
  2266. {
  2267.   PixmapWidget PW = (PixmapWidget) w;
  2268.   
  2269.   PW->pixmap.buffer_mark = PW->pixmap.mark;
  2270.   
  2271.   if (QuerySet(PW->pixmap.mark.from_x, PW->pixmap.mark.from_y)) {
  2272.     XFillRectangle(dpy, XtWindow(PW), PW->pixmap.highlighting_gc,
  2273.            InWindowX(PW, PW->pixmap.mark.from_x), 
  2274.            InWindowY(PW, PW->pixmap.mark.from_y), 
  2275.            InWindowX(PW, PW->pixmap.mark.to_x + 1) - 
  2276.            InWindowX(PW, PW->pixmap.mark.from_x),
  2277.            InWindowY(PW, PW->pixmap.mark.to_y + 1) -
  2278.            InWindowY(PW, PW->pixmap.mark.from_y));
  2279.     
  2280.     PW->pixmap.mark.from_x = PW->pixmap.mark.from_y = NotSet;
  2281.     PW->pixmap.mark.to_x = PW->pixmap.mark.to_y = NotSet;
  2282.   }
  2283. }
  2284.  
  2285. #if NeedFunctionPrototypes
  2286. void PWMark(Widget w, Position from_x, Position from_y, 
  2287.         Position to_x, Position to_y)
  2288. #else
  2289. void PWMark(w, from_x, from_y, to_x, to_y)
  2290.      Widget w;
  2291.      Position from_x, from_y, to_x, to_y;
  2292. #endif
  2293. {
  2294.   PixmapWidget PW = (PixmapWidget) w;
  2295.   
  2296.   PWUnmark(w);
  2297.   
  2298.   if (QuerySet(from_x, from_y)) {
  2299.     if ((from_x == to_x) && (from_y == to_y)) {
  2300.       /*
  2301.     PW->pixmap.mark.from_x = 0;
  2302.     PW->pixmap.mark.from_y = 0;
  2303.     PW->pixmap.mark.to_x = PW->pixmap.image->width - 1;
  2304.     PW->pixmap.mark.to_y = PW->pixmap.image->height - 1;
  2305.     */
  2306.       return;
  2307.     }
  2308.     else {
  2309.       QuerySwap(from_x, to_x);
  2310.       QuerySwap(from_y, to_y);
  2311.       from_x = max(0, from_x);
  2312.       from_y = max(0, from_y);
  2313.       to_x = min(PW->pixmap.image->width - 1, to_x);
  2314.       to_y = min(PW->pixmap.image->height - 1, to_y);
  2315.       
  2316.       PW->pixmap.mark.from_x = from_x;
  2317.       PW->pixmap.mark.from_y = from_y;
  2318.       PW->pixmap.mark.to_x = to_x;
  2319.       PW->pixmap.mark.to_y = to_y;
  2320.     }
  2321.     
  2322.     XFillRectangle(dpy, XtWindow(PW), PW->pixmap.highlighting_gc,
  2323.            InWindowX(PW, PW->pixmap.mark.from_x),
  2324.            InWindowY(PW, PW->pixmap.mark.from_y), 
  2325.            InWindowX(PW, PW->pixmap.mark.to_x + 1) -
  2326.            InWindowX(PW, PW->pixmap.mark.from_x),
  2327.            InWindowY(PW, PW->pixmap.mark.to_y +1) - 
  2328.            InWindowY(PW, PW->pixmap.mark.from_y));
  2329.   }
  2330. }
  2331.  
  2332. #if NeedFunctionPrototypes
  2333. void PWUndo(Widget w)
  2334. #else
  2335. void PWUndo(w)
  2336.      Widget w;
  2337. #endif
  2338. {
  2339.   PixmapWidget PW = (PixmapWidget) w;
  2340.   Position x, y;
  2341.   int tmp_nextensions;
  2342.   XpmExtension *tmp_extensions;
  2343.   XPoint tmp_hot;
  2344.   XImage *tmp_image, *mask_tmp_image;
  2345.   PWArea tmp_mark;
  2346.   Pixel color;
  2347.   
  2348.   tmp_image = PW->pixmap.image;
  2349.   mask_tmp_image = PW->pixmap.mask_image;
  2350.   PW->pixmap.image = PW->pixmap.buffer;
  2351.   PW->pixmap.mask_image = PW->pixmap.mask_buffer;
  2352.   PW->pixmap.buffer = tmp_image;
  2353.   PW->pixmap.mask_buffer = mask_tmp_image;
  2354.  
  2355.   tmp_hot = PW->pixmap.hot;
  2356.   tmp_mark = PW->pixmap.mark;
  2357.   PW->pixmap.mark = PW->pixmap.buffer_mark;
  2358.   PW->pixmap.buffer_mark= tmp_mark;
  2359.  
  2360.   /* erase extensions then save */
  2361.   /* This part is commented now cause it seems to be useless */
  2362. /*  if (PW->pixmap.redrawCallback)
  2363.       PW->pixmap.redrawCallback( w, Clear ); */
  2364.   tmp_nextensions = PW->pixmap.nextensions;
  2365.   tmp_extensions  = PW->pixmap.extensions;
  2366.   PW->pixmap.nextensions = PW->pixmap.buffer_nextensions;
  2367.   PW->pixmap.extensions  = PW->pixmap.buffer_extensions;
  2368.   PW->pixmap.buffer_nextensions = tmp_nextensions;
  2369.   PW->pixmap.buffer_extensions  = tmp_extensions;
  2370.  
  2371.   if ((PW->pixmap.image->width != PW->pixmap.buffer->width) ||
  2372.       (PW->pixmap.image->height != PW->pixmap.buffer->height))
  2373.     {
  2374.       PW->pixmap.width = PW->pixmap.image->width;
  2375.       PW->pixmap.height = PW->pixmap.image->height;
  2376.       InternalResize(PW);
  2377.     }
  2378.   else
  2379.     {
  2380.       for (x = 0; x < PW->pixmap.image->width; x++)
  2381.     for (y = 0; y < PW->pixmap.image->height; y++)
  2382.       if (GetPxlFromImageAndMask(PW->pixmap.buffer, PW->pixmap.mask_buffer,
  2383.                      x, y) != (color = GetPxl(PW, x, y)))
  2384.         {
  2385.           DrawPoint(PW, x, y, color, NotLazy);
  2386.         }
  2387.   
  2388.       /* Now treating Undo copy seperatly :
  2389.      when mark is set and is different from buffer one, redraw them */
  2390.       if ((QuerySet(PW->pixmap.mark.from_x, PW->pixmap.mark.from_y)) &&
  2391.       (QuerySet(PW->pixmap.buffer_mark.from_x, 
  2392.             PW->pixmap.buffer_mark.from_y))
  2393.       && ((PW->pixmap.mark.from_x != PW->pixmap.buffer_mark.from_x) ||
  2394.           (PW->pixmap.mark.from_y != PW->pixmap.buffer_mark.from_y) ||
  2395.           (PW->pixmap.mark.to_x != PW->pixmap.buffer_mark.to_x) ||
  2396.           (PW->pixmap.mark.to_y != PW->pixmap.buffer_mark.to_y)))
  2397.     {
  2398.       PWRedrawPoints((Widget) PW, PW->pixmap.mark.from_x, 
  2399.              PW->pixmap.mark.from_y, 
  2400.              PW->pixmap.mark.to_x, 
  2401.              PW->pixmap.mark.to_y);
  2402.       PWRedrawPoints((Widget) PW, PW->pixmap.buffer_mark.from_x, 
  2403.              PW->pixmap.buffer_mark.from_y, 
  2404.              PW->pixmap.buffer_mark.to_x, 
  2405.              PW->pixmap.buffer_mark.to_y);
  2406.     }
  2407.     }
  2408.  
  2409.   PWSetHotSpot(w, PW->pixmap.buffer_hot.x, PW->pixmap.buffer_hot.y);
  2410.   PW->pixmap.buffer_hot = tmp_hot;
  2411.  
  2412.   /* This part is commented now cause it seems to be useless */
  2413. /*  if (PW->pixmap.redrawCallback)
  2414.       PW->pixmap.redrawCallback( w, Set );*/
  2415. }
  2416.  
  2417.  
  2418. #if NeedFunctionPrototypes
  2419. void PWRotateBufferAndImage(Widget w)
  2420. #else
  2421. void PWRotateBufferAndImage(w)
  2422.      Widget w;
  2423. #endif
  2424. {
  2425.   PixmapWidget PW = (PixmapWidget) w;
  2426.   XPoint tmp_hot;
  2427.   XImage *tmp_image, *mask_tmp_image;
  2428.   Boolean SetHotSpot = False;
  2429.  
  2430.   if (QuerySet(PW->pixmap.mark.from_x, PW->pixmap.mark.from_y)) {
  2431.       /* Rotate Image and marked area */
  2432.       Dimension width, height;
  2433.       XImage *storage, *mask_storage;
  2434.  
  2435.       width = PW->pixmap.mark.to_x - PW->pixmap.mark.from_x + 1;
  2436.       height = PW->pixmap.mark.to_y - PW->pixmap.mark.from_y + 1;
  2437.       
  2438.       storage = CreatePixmapImage(PW, width, height);
  2439.       mask_storage = CreateMaskImage(PW, width, height);
  2440.       
  2441.       CopyImageData(PW->pixmap.image, storage,
  2442.             PW->pixmap.mark.from_x,  PW->pixmap.mark.from_y,
  2443.             PW->pixmap.mark.to_x,  PW->pixmap.mark.to_y,
  2444.             0, 0);
  2445.       
  2446.       CopyImageData(PW->pixmap.mask_image, mask_storage,
  2447.             PW->pixmap.mark.from_x,  PW->pixmap.mark.from_y,
  2448.             PW->pixmap.mark.to_x,  PW->pixmap.mark.to_y,
  2449.             0, 0);
  2450.       tmp_image = PW->pixmap.image;
  2451.       mask_tmp_image = PW->pixmap.mask_image;
  2452.       tmp_hot = PW->pixmap.hot;
  2453.       PW->pixmap.image = storage;
  2454.       PW->pixmap.mask_image = mask_storage;
  2455.  
  2456.       /* reset all marked area as there are problems with undo */
  2457.       PW->pixmap.mark.from_x = PW->pixmap.mark.to_x = NotSet;
  2458.       PW->pixmap.mark.from_y = PW->pixmap.mark.to_y = NotSet;
  2459.       PW->pixmap.buffer_mark.from_x = PW->pixmap.buffer_mark.to_x = NotSet;
  2460.       PW->pixmap.buffer_mark.from_y = PW->pixmap.buffer_mark.to_y = NotSet;
  2461.   } else {
  2462.       /* Rotate Image and Cut/Insert buffer */
  2463.       SetHotSpot = True;
  2464.       tmp_image = PW->pixmap.image;
  2465.       mask_tmp_image = PW->pixmap.mask_image;
  2466.       tmp_hot = PW->pixmap.hot;
  2467.       PW->pixmap.image = PW->pixmap.storage;
  2468.       PW->pixmap.mask_image = PW->pixmap.mask_storage;
  2469.       PW->pixmap.storage = tmp_image;
  2470.       PW->pixmap.mask_storage = mask_tmp_image;
  2471.   }
  2472.  
  2473.   if ((PW->pixmap.image->width != tmp_image->width) ||
  2474.       (PW->pixmap.image->height != tmp_image->height)) {
  2475.       PW->pixmap.width = PW->pixmap.image->width;
  2476.       PW->pixmap.height = PW->pixmap.image->height;
  2477.       InternalResize(PW);
  2478.   }
  2479.   else PWRedraw(w);
  2480.  
  2481.   if (SetHotSpot) /* if storage taken from buffer */
  2482.     PWSetHotSpot(w, PW->pixmap.storage_hot.x, PW->pixmap.storage_hot.y);
  2483.   else {
  2484.       DestroyPixmapImage(&tmp_image);
  2485.       DestroyMaskImage(&mask_tmp_image);
  2486.   }
  2487.   
  2488.   PW->pixmap.storage_hot = tmp_hot;
  2489. }
  2490.  
  2491.  
  2492. #if NeedFunctionPrototypes
  2493. void PWHighlightAxes(Widget w)
  2494. #else
  2495. void PWHighlightAxes(w)
  2496.      Widget w;
  2497. #endif
  2498. {
  2499.   PixmapWidget PW = (PixmapWidget) w;
  2500.   
  2501.   XDrawLine(dpy, XtWindow(PW),
  2502.         PW->pixmap.framing_gc,
  2503.         InWindowX(PW, 0), 
  2504.         InWindowY(PW, 0),
  2505.         InWindowX(PW, PW->pixmap.width),
  2506.         InWindowY(PW, PW->pixmap.height));
  2507.   XDrawLine(dpy, XtWindow(PW),
  2508.         PW->pixmap.framing_gc,
  2509.         InWindowX(PW, PW->pixmap.width),
  2510.         InWindowY(PW, 0), 
  2511.         InWindowX(PW, 0),
  2512.         InWindowY(PW, PW->pixmap.height));
  2513.   if (PWQueryGrid((Widget)PW))
  2514.     {
  2515.       if ((((int)(PW->pixmap.height / 2.0)) * 2) != PW->pixmap.height)
  2516.     XDrawLine(dpy, XtWindow(PW),
  2517.           PW->pixmap.framing_gc,
  2518.           InWindowX(PW, 0),
  2519.           InWindowY(PW, PW->pixmap.height / 2.0),
  2520.           InWindowX(PW, PW->pixmap.width),
  2521.           InWindowY(PW, PW->pixmap.height / 2.0));
  2522.       if ((((int)(PW->pixmap.width / 2.0)) * 2) != PW->pixmap.width)
  2523.     XDrawLine(dpy, XtWindow(PW),
  2524.           PW->pixmap.framing_gc,
  2525.           InWindowX(PW, PW->pixmap.width / 2.0),
  2526.           InWindowY(PW, 0),
  2527.           InWindowX(PW, PW->pixmap.width / 2.0),
  2528.           InWindowY(PW, PW->pixmap.height));
  2529.     }
  2530. }
  2531.  
  2532. #if NeedFunctionPrototypes
  2533. void PWSetForeground(Widget w, Pixel color)
  2534. #else
  2535. void PWSetForeground(w,color)
  2536.      Widget w;
  2537.      Pixel color;
  2538. #endif     
  2539. {
  2540.   PixmapWidget PW = (PixmapWidget) w;
  2541.   
  2542.   XSetForeground(dpy,PW->pixmap.drawing_gc, color);
  2543.   PW->pixmap.foreground_pixel = color;
  2544. }
  2545.  
  2546.  
  2547.  
  2548. /* drag a rectangle representing the extent of the text */
  2549.  
  2550. #if NeedFunctionPrototypes
  2551. void PWDragText(Widget w, Position at_x, Position at_y, int value)
  2552. #else
  2553. void PWDragText(w, at_x, at_y, value)
  2554.      Widget    w;
  2555.      Position    at_x, at_y;    /* text origin */
  2556.      int        value;        /* unused */
  2557. #endif
  2558. {
  2559.   PixmapWidget PW = (PixmapWidget) w;
  2560.  
  2561. /*
  2562.   calculate text extent 
  2563.   translate from text origin to upper left of text extent 
  2564.   draw rectangle from upper left to lower right of text extent
  2565.  
  2566.   Dimension width  = PW->pixmap.text_rbearing - PW->pixmap.text_lbearing;
  2567.   Dimension height = PW->pixmap.text_ascent + PW->pixmap.text_descent;
  2568.   Position x = at_x + PW->pixmap.text_lbearing;
  2569.   Position y = at_y - PW->pixmap.text_ascent + 1;
  2570.   PWDrawRectangle(w, 
  2571.           x, y,
  2572.                   x + width, y + height,
  2573.           value);
  2574. */
  2575.  
  2576.   PWDrawText(w, at_x, at_y, value);
  2577. }
  2578.  
  2579. #if NeedFunctionPrototypes
  2580. void PWDrawText(Widget w, Position at_x, Position at_y, int value)
  2581. #else
  2582. void PWDrawText(w, at_x, at_y, value)
  2583.      Widget    w;
  2584.      Position    at_x, at_y;    /* text origin */
  2585.      int        value;
  2586. #endif
  2587. {
  2588.   PixmapWidget PW = (PixmapWidget) w;
  2589.  
  2590.   Pixmap     pixmap;
  2591.   XImage     *image;
  2592.   GC         gc;
  2593.   XGCValues  gcv;
  2594.   Position   x, y, i, j;
  2595.   Dimension  width, height;
  2596.  
  2597.   if ( ! PW->pixmap.text_string || 
  2598.        ! PW->pixmap.font_struct ||
  2599.        strlen(PW->pixmap.text_string) == 0 )
  2600.       return;
  2601.  
  2602.   /* 
  2603.      To draw text: 
  2604.      put text in tmp pixmap of depth 1 then get image 
  2605.      foreach pixel in image, if set draw into pixmapwidget 
  2606.   */
  2607.  
  2608.   /* text extent, add 1 pixel pad because fonts vary is how ascent is defined */
  2609.   width  = PW->pixmap.text_rbearing - PW->pixmap.text_lbearing + 2;
  2610.   height = PW->pixmap.text_ascent + PW->pixmap.text_descent + 2;
  2611.  
  2612.   /* create white pixmap size of text extent with depth one */
  2613.   pixmap = XCreatePixmap( dpy, XtWindow(PW), width, height, 1 );
  2614.   gcv.font       = PW->pixmap.font_struct->fid;
  2615.   gcv.function   = GXcopy;
  2616.   gcv.foreground = WhitePixel( dpy, screen );
  2617.   gcv.background = WhitePixel( dpy, screen );
  2618.   gc = XCreateGC( dpy, pixmap, 
  2619.                   GCFunction | GCFont | GCForeground | GCBackground, 
  2620.                   &gcv );
  2621.   XFillRectangle( dpy, pixmap, gc, 0, 0, width, height ); /* clear */
  2622.   
  2623.   /* draw text in pixmap */
  2624.   x = (PW->pixmap.text_lbearing < 0) ? - PW->pixmap.text_lbearing : 0;
  2625.   y = PW->pixmap.text_ascent /* - 1 */; /* include pad */
  2626.   XSetForeground( dpy, gc, BlackPixel(dpy, screen) );
  2627.   XDrawString( dpy, pixmap, gc, x, y,
  2628.                PW->pixmap.text_string, strlen(PW->pixmap.text_string) );
  2629.  
  2630.   /* get image of text */
  2631.   image = XGetImage(dpy, pixmap, 0, 0, width, height, -1/*allplanes*/,ZPixmap);
  2632.  
  2633.   /* translate (at_x,at_y) from text origin to upper left of text extent */
  2634.   x = at_x;
  2635.   y = at_y;
  2636.   x += PW->pixmap.text_lbearing;
  2637.   y -= PW->pixmap.text_ascent - 1;
  2638.  
  2639.   /* foreach set pixel in image, draw into pixmapwidget */
  2640.   for (i = 0; i < width; i++) {
  2641.       for (j = 0; j < height; j++) {
  2642.  
  2643.           if (!QueryInPixmap(PW, x + i, y + j)) continue;
  2644.  
  2645.           if ( XGetPixel(image, i, j) == BlackPixel(dpy, screen) ) {
  2646.               PWDrawPoint( (Widget) PW, x + i, y + j, value );
  2647.           }
  2648.       }
  2649.   }
  2650.   
  2651.   /* clean up */
  2652.   XFreePixmap( dpy, pixmap );
  2653.   XFreeGC( dpy, gc );
  2654.   XDestroyImage( image );
  2655. }
  2656.